N Queens Puzzle - 此解决方案中的回溯位置在哪里?

时间:2015-11-24 06:32:59

标签: c algorithm backtracking n-queens

在研究众所周知的N Queens puzzle时,我在C中遇到了this直截了当且易于理解的实现:

#include<stdio.h>
#include<math.h>

int board[20],count;

int main()
{
 int n,i,j;
 void queen(int row,int n);

 printf(" - N Queens Problem Using Backtracking -");
 printf("\n\nEnter number of Queens:");
 scanf("%d",&n);
 queen(1,n);
 return 0;
}

//function for printing the solution
void print(int n)
{
 int i,j;
 printf("\n\nSolution %d:\n\n",++count);

 for(i=1;i<=n;++i)
  printf("\t%d",i);

 for(i=1;i<=n;++i)
 {
  printf("\n\n%d",i);
  for(j=1;j<=n;++j) //for nxn board
  {
   if(board[i]==j)
    printf("\tQ"); //queen at i,j position
   else
    printf("\t-"); //empty slot
  }
 }
}

/*funtion to check conflicts
If no conflict for desired postion returns 1 otherwise returns 0*/
int place(int row,int column)
{
 int i;
 for(i=1;i<=row-1;++i)
 {
  //checking column and digonal conflicts
  if(board[i]==column)
   return 0;
  else
   if(abs(board[i]-column)==abs(i-row))
    return 0;
 }

 return 1; //no conflicts
}

//function to check for proper positioning of queen
void queen(int row,int n)
{
 int column;
 for(column=1;column<=n;++column)
 {
  if(place(row,column))
  {
   board[row]=column; //no conflicts so place queen
   if(row==n) //dead end
    print(n); //printing the board configuration
   else //try queen with next position
    queen(row+1,n);
  }
 }
}

然而,尽管大部分内容对我来说都是正确的,但我看不到其中的回溯。我错过了什么?

在我看来,在queen()函数中,应该在for循环之后进行检查,以查看搜索是否在该特定行/后执行中没有成功而耗尽,如果是,则回溯简单地用row-1调用自己。这个假设是否正确?

3 个答案:

答案 0 :(得分:3)

让我们深入了解一下这段代码:

void queen(int row,int n)
{
 int column;
 for(column=1;column<=n;++column)
 {
  if(place(row,column))
  {
   board[row]=column; //no conflicts so place queen
   if(row==n) //dead end
    print(n); //printing the board configuration
   else //try queen with next position
    queen(row+1,n);
  }
 }
}

是的,它是回溯。因为它会尝试每个可能的解决方案候选人,直到完成一些条件。对于某个row值,for(column=1;column<=n;++column)将确保尝试column的每个可能值,并检查place(row,column)是否可行,然后深入row + 1 。完成此操作后,此算法将恢复到下一列。

换句话说,该算法将打印n - 女王的所有可能解决方案。

答案 1 :(得分:1)

回溯隐藏在函数queen()的递归调用中。它通过try和error检查列的列,如果发现命中则放置。然后它以递归方式调用具有下一行的函数queen(),并遍历列的下一行列,直到找到无法打败后者的位置。并且重复此递归调用,直到放置所有皇后。

回溯的主要思想是尝试和错误的方法。如果不能放置所有皇后,算法会跳回一个树分支,然后再从下一列开始。

答案 2 :(得分:0)

回溯是由return函数末尾的implucit queens语句完成的。在检查完所有列之后,即您提到的详尽搜索。

为了更清楚地看到它,重写函数以使用显式堆栈数据结构代替隐式调用堆栈。然后回溯将被明确地表达为pop(stack)