简体   繁体   English

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

[英]N Queens Puzzle - Where is the Backtracking in this solution?

While studying the well known N Queens puzzle , I came across this straightforward and easy to understand implementation in C: 在研究众所周知的N Queens拼图时 ,我在C中遇到了这个简单易懂的实现:

#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);
  }
 }
}

However, as much as most of it looks correct to me, I cannot see the backtracking in it. 然而,尽管大多数看起来对我来说都是正确的,但我看不到它的回溯 What am I missing? 我错过了什么?

In my opinion, in the queen() function, there should be a check after the for loop to see whether the search exhausted without success for that particular row/queen, and if so, backtrack by simply calling itself with row-1. 在我看来,在queen()函数中,应该在for循环之后进行检查,以查看搜索是否已经耗尽而没有成功执行该特定行/后,如果是,则通过简单地使用row-1调用自身来进行回溯。 Is this assumption correct? 这个假设是否正确?

let's get deeper look in this code: 让我们深入了解一下这段代码:

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);
  }
 }
}

Yes, it's backtracking . 是的,这是回溯 Since it'll try every possible solution candidate until the some finish condition. 因为它会尝试每个可能的解决方案候选人,直到完成一些条件。 on some row value, for(column=1;column<=n;++column) will ensure to try every possible value of column and check if it feasible with place(row,column) , then go deeper to row +1. 对于某个row值, for(column=1;column<=n;++column)将确保尝试column每个可能值,并检查它是否可以与place(row,column) ,然后更深入到row +1。 After finishing this, this algorithm will resume to next column. 完成此操作后,此算法将恢复到下一列。

In other word, this algorithm will print every possible solution, of n -queen. 换句话说,该算法将打印n -queen的每个可能的解决方案。

The backtracking is hidden in the recursive call of the function queen() . 回溯隐藏在函数queen()的递归调用中。 It checks column for column by try and error and places the queen if found a hit. 它通过try和error检查列的列,如果发现命中,则放置后。 Then it recursively calls the function queen() with the next row and traverses this next row column for column until it finds a place where the queen cannot be beaten. 然后它递归调用函数queen()和下一行,并遍历列的下一行列,直到它找到一个不能打败后者的地方。 And this recursive call is repeated until all queens are placed. 并且重复此递归调用,直到放置所有皇后。

The main idea of backtracking is the try and error approach. 回溯的主要思想是尝试和错误的方法。 If not all queens can be placed, the algorithm jumps back one tree branch and begins again with the next column. 如果不能放置所有皇后,则算法会跳回一个树分支并再次从下一列开始。

The backtracking is done by the implucit return statement at the end of queens function. 回溯是由queens功能结束时的implucit return语句完成的。 It comes after all columns are checked, ie the exhaustive search you mentioned. 检查所有列后,即您提到的详尽搜索。

To see it more clearly, rewrite the function to use an explicit stack data structure in lieu of the implicit call stack. 为了更清楚地看到它,重写函数以使用显式堆栈数据结构代替隐式调用堆栈。 Then the backtracking will be expressed ecplicitly as pop(stack) . 然后回溯将以pop(stack)形式表达。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM