要在n*n的国际象棋棋盘上,在不同的每行每列都放置有一个皇后,而皇后之间不可以在同一行同一列和同一对角线上,给定n,问有多少种放皇后的方法。
分析:利用深度搜索Dfs进行穷举式的搜索,在搜索过程中剔除无用的解。
思路:设定对每行的每个棋格进行逐个遍历,如果这个棋子放置符合规则就进行深一步的放置,即跳到下一行去找符合放置的棋子,周而复始,直到行的值等于n。
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
int n,cnt=0;
bool place(int k/*当前行数*/,int x[])
{
for(int j=1;j<k;j++)//Judging the site whether places or not
{
if((x[k]==x[j]||abs(k-j)==abs(x[k]-x[j])))
return false;
}
return true;
}
void dfs(int t,int x[])//backtrack
{
if(t==n+1)//t>n
cnt++;
else
{
for(int i=1;i<=n;i++)//the essential part
{
x[t] = i;
if(place(t,x))
dfs(t+1,x);
}
}
}
int main()
{
int x[n+1];//存储列号
cin>>n;
memset(x,0,sizeof(x));
dfs(1,x);
cout<<cnt<<endl;
}
其实没有必要去过深入的知道回溯的过程,因为实在在复杂,只要自然语义的理解就可以了。反正它的过程就是一颗树,先搜出一个解,然后回到父节点,去搜下面的子节点,当都搜过了,父节点就没有节点可搜了,继续回到它的父节点往下搜索,而这个过程就是在递归中实现的,递归第一次直接到后面,然后从何往前,只要递归语句在一个for循环里,就可以达到回溯的效果。
ps:研究这个问题真是太爽了,星期六想了一天,晚上上算法课又刚好讲了回溯法,如鱼得水。不过还是要感谢我身边还有一些优秀的同学让我每天激情澎湃的搞编程啦,昨天才上手的C++,因为要搞STL了。。。感觉用起来比C爽了不少…嘻嘻,欲知后事如何,请看下回分解。