簡體   English   中英

在回溯遞歸算法中確定基本條件

[英]Deciding the base condition in backtracking recursive algorithm

我正在解決N皇后問題,我們需要在4×4國際象棋棋盤上放置4個皇后,這樣就不會有兩個皇后可以相互攻擊。 我之前嘗試過這個,但我的方法並沒有涉及回溯,所以我再次嘗試。 代碼片段是

int size=4,i,j;
int arr[4][4];
int lastjindex[4]; // to store the last location which we may need to backtrack



void placeQueen(int i,int j)
{
    int availableornot=0;

    for(j=0;j<size;j++)
    {
        if(isAvailable(i,j)==1)
        {
            availableornot=1;
            break;
        }
    }

    if(availableornot==1)
    {
        arr[i][j]=1;
        lastjindex[i]=j;

        if((i+1)!=size)
        {
            placeQueen(i+1,0);
        }
    }

    else
    {
        // no column was availabe so we backtrack
        arr[i-1][lastjindex[i-1]]=0;
        placeQueen(i-1,lastjindex[i-1]+1);
    }
}

如果arr [i] [j]沒有受到攻擊,則isAvailable()方法返回1,否則返回0。

int isAvailable(int i,int j)
{
    int m,n,flag=0;

    for(m=0;m<i;m++)
    {
        for(n=0;n<size;n++)
        {
            int k=abs(i-m);
            int l=abs(j-n);

            if(arr[m][j]==0 || arr[k][l]==0)
            {
                flag=1;
                break;
                // means that spot is available
            }
        }
    }
    return flag;
}

我從main調用上面的方法

placeQueen(0,0);

我的程序編譯成功但它打印全部為零。


我的遞歸有問題嗎? 當我試圖學習如何實現回溯算法時,請幫我糾正我的代碼!


此外,我無法決定結束遞歸的基本條件。 我如何在這里選擇它?

您發布的代碼中沒有打印。 如果你在回溯后進行打印,你將回到棋盤上沒有皇后的初始狀態。 放置N個皇后后打印,這也是遞歸的最終條件。 如果您只想打印一個解決方案,請在打印后退出,或者設置一個標志,告訴調用者您已完成,以便完全彈出。 如果您打印所有解決方案,那將包括反射和旋轉。 您可以通過僅在第一級中放置大小/ 2的女王來消除一個反射軸。

此外,您的代碼中存在一些明顯的邏輯錯誤,例如

arr[m][j]==0 || arr[k][l]==0

只有在沒有攻擊文件並且不會沿着對角線攻擊時,才能放置女王。 使用調試器或將printfs添加到代碼中以跟蹤它試圖放置皇后的位置 - 這將幫助您弄清楚它做錯了什么。

除了錯誤之外,你的isAvailable非常低效。 你想知道[i,j]方是沿着文件還是對角線被攻擊。 為此,您應該在前一個皇后的行上有一個循環for (m = 0; m < i; m++) ,但是您只需要三個測試而不是循環來檢查文件和對角線。 一旦你在文件或對角線上找到任何前任女王,你就完成了,並且方塊不可用 - 返回false。 (並且忽略那些告訴你一個函數應該只有一個回報的人 - 他們錯了,這里有很長時間的討論,甚至在代碼中對錯誤率的科學研究也證明了這一點。)只有在沒有以前的女王是發現是廣場可用。

你的placeQueen也錯了。 對於一行中的每個可用方塊,您需要放置一個女王然后遞歸,但您只是找到第一個可用的方塊。 簡單地通過移除你放置的女王然后返回來實現回溯......之前的placeQueen將嘗試下一個可用的地點。

再次,跟蹤代碼以查看它正在做什么。 而且,更重要的是,要考慮所需要的邏輯。 用文字寫出你的算法,說服自己它會解決問題,然后編寫代碼來執行算法。

#include <stdio.h>

#define SIZE 4
int size=SIZE;
int arr[SIZE][SIZE] = { 0 };

void placeQueen(int col){
    int r,c;
    if(col == size){//all queen put!
        //print out
        for(r = 0;r<size;++r){
            for(c = 0;c<size;++c)
                printf("%d", arr[c][r]);
            printf("\n");
        }
        printf("\n");
        return ;
    }
    for(r=0;r<size;++r){
        if(isAvailable(col, r)==1){
            arr[col][r]=1;
            placeQueen(col+1);
            arr[col][r]=0;//reset
        }
    }
}

int isAvailable(int col,int row){
    int c;

    for(c=0;c<col;++c){
        int d = col - c;
        if(arr[c][row]==1)
            return 0;//queen already same row
        if(row+d < size && arr[c][row+d]==1 || row-d >= 0 && arr[c][row-d]==1)
            return 0;//queen already same slanting position
    }
    return 1;
}

int main(){
    placeQueen(0);
    return 0;
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM