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

Posted

技术标签:

【中文标题】N Queens Puzzle - 此解决方案中的回溯在哪里?【英文标题】:N Queens Puzzle - Where is the Backtracking in this solution? 【发布时间】:2015-11-24 06:32:58 【问题描述】:

在研究众所周知的N Queens puzzle 时,我遇到了this 简单易懂的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);
  
 

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

在我看来,在queen() 函数中,应该在for 循环之后检查该特定行/皇后的搜索是否已用尽而没有成功,如果是,则通过简单地调用自身来回溯第 1 行。这个假设正确吗?

【问题讨论】:

【参考方案1】:

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

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&lt;=n;++column) 将确保尝试column 的所有可能值并检查place(row,column) 是否可行,然后深入row+1。完成此操作后,此算法将继续到下一列。

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

【讨论】:

接受,感谢您对的洞察力“此算法将打印每个可能的解决方案”【参考方案2】:

回溯隐藏在函数queen()的递归调用中。它通过尝试和错误检查列,如果发现命中则放置女王。然后它用下一行递归调用函数queen(),并逐列遍历下一行,直到找到一个无法击败女王的地方。并且重复此递归调用,直到放置所有皇后。

回溯的主要思想是试错法。如果不能放置所有皇后,算法会跳回一个树枝并从下一列重新开始。

【讨论】:

这就是我最初的想法,但如果行/皇后 1、2、3 和皇后 4 一切顺利,到达循环的末尾怎么办?直觉上,这可能表明皇后 3 甚至 2 或 1 被“过早”放置,需要尝试不同的位置。我在这段代码中看不到重新定位皇后 1 的能力,例如,成功定位之后。想法? 啊,好的。我现在看到了。在@ibrohimislam 的回答的帮助下,说明“这个算法将打印所有可能的解决方案,n-queen”,结合你写的关于“尝试和错误方法”的内容,我现在明白if(row==n) print(n); 是一个整体并且解决方案的关键部分。【参考方案3】:

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

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

【讨论】:

以上是关于N Queens Puzzle - 此解决方案中的回溯在哪里?的主要内容,如果未能解决你的问题,请参考以下文章

1128 N Queens Puzzle (20分)

PAT A1128 N Queens Puzzle (20 分)

POJ 3239 -- Solution to the n Queens Puzzle

1128 N Queens Puzzle (20 分)难度: 一般 / 知识点: 模拟

如何解决方案中的 n-queens

Python中的N-Queens程序