我正在解决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);
我的程序编译成功,但它打印全部为零。
我的递归有问题吗?当我试图学习如何实现回溯算法时,请帮我纠正我的代码!
此外,我无法确定结束递归的基本条件。我如何在这里选择它?
答案 0 :(得分:1)
您发布的代码中没有打印。如果你在回溯后进行打印,你将回到棋盘上没有皇后的初始状态。放置N个皇后后打印,这也是递归的最终条件。如果您只想打印一个解决方案,请在打印后退出,或者设置一个标志,告诉调用者您已完成,以便完全弹出。如果您打印所有解决方案,那将包括反射和旋转。您可以通过仅在第一级中放置大小/ 2的女王来消除一个反射轴。
此外,您的代码中存在一些明显的逻辑错误,例如
arr[m][j]==0 || arr[k][l]==0
只有在没有攻击 文件的情况下,才能放置女王。它不会沿着对角线受到攻击。使用调试器或将printfs添加到代码中以跟踪它试图放置皇后的位置 - 这将帮助您弄清楚它做错了什么。
除了错误之外,你的isAvailable
效率非常低。你想知道[i,j]方是沿着文件还是对角线被攻击。为此,您应该在前一个皇后for (m = 0; m < i; m++)
的行上有一个循环,但是您只需要三个测试而不是循环来检查文件和对角线。一旦你在文件或对角线上找到任何前任女王,你就完成了,并且方块不可用 - 返回false。 (并且忽略那些告诉你一个函数应该只有一个回报的人 - 他们错了,这里有很长时间的讨论,甚至在代码中对错误率的科学研究也证明了这一点。)只有在没有以前的女王是发现是可用的广场。
你的placeQueen
也错了。对于行中每个可用的正方形,您需要放置一个女王然后递归,但您只是找到第一个可用的正方形。只需移除你放置的女王然后返回就可以实现回溯......之前的placeQueen会尝试下一个可用的地点。
再次,跟踪代码以查看它正在做什么。而且,更重要的是,要考虑所需要的逻辑。用文字写出你的算法,说服自己解决问题,然后编写代码来执行算法。
答案 1 :(得分:1)
#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;
}