[英]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.