HDU2553 N皇后问题——DFS
Posted tuyang1129
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU2553 N皇后问题——DFS相关的知识,希望对你有一定的参考价值。
N皇后问题
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 32229 Accepted Submission(s): 13874
你的任务是,对于给定的N,求出有多少种合法的放置方法。
题意:中文题。。。。。
思路:非常经典的搜索问题,用DFS来写。在棋盘中的棋,它的上下左右,以及左上,右上,左下,右下都不能有棋。因为是N*N的棋盘要放N个棋,可以知道一定是每一行放一个棋,所以我们可以按行进行搜索,逐一确定每一行的棋放在这一行的哪一个位置。
这样有什么好处呢?这样就可以不用担心会发生两个棋子在同一行的情况了,而且也不用管这一行之前的行的情况了,因为能搜索到这一行,之前的每一个都应该是合法的。
然后如何标记那些位置不能走呢?首先,行不用标记,原因上面说了,列也好办,开一个标记列的数组就行了。
那左下和右下怎么办呢?仔细观察可以发现当前点到左下角45度这一条线路的所有点行数+列数的值都是相等的,而到右下角45度这一条线路行数-列数的值都是相等的,所以我们可以考虑用行和列的和来标记左下,行和列的差来标记右下,这样就是普通的DFS模板了。
这题还有一个坑点,就是n是循环输入的,一组测试数据要DFS很多次,如果直接交的话会超时。因为n<=10,所以可以提前求出n==1到10的答案,存下,然后再输入n的时候直接用就行了。
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<string> 5 #include<cmath> 6 #include<algorithm> 7 #include<stack> 8 #include<queue> 9 #define eps 1e-7 10 #define ll long long 11 #define inf 0x3f3f3f3f 12 #define pi 3.141592653589793238462643383279 13 using namespace std; 14 int ldown[20],rdown[30],vcolu[30]; //ldown标记左下,rdown标记右下,vcolu标记列 15 int n,ans[20]; 16 17 void DFS(int all,int cnt) 18 { 19 if(cnt == all+1) //如果最后一行也已经放了棋子,递归到了n+1行,答案++; 20 { 21 ans[all]++; 22 return; 23 } 24 25 for(int i=1; i<=all; ++i) //枚举这一行的每一列 26 { 27 if(!vcolu[i] && !ldown[cnt+i] && !rdown[10+cnt-i]) //如果列,左下,右下都未标记不能走,则这一点可以走 28 { 29 vcolu[i] = 1; //列标记为不能走 30 ldown[cnt+i] = 1; //左下标记为不能走 31 rdown[10+cnt-i] = 1; //右下。。。因为cnt-i可能为负,所以加上10避免 32 DFS(all,cnt+1); //递归搜索下一行 33 vcolu[i] = 0; //回溯 34 ldown[cnt+i] = 0; 35 rdown[10+cnt-i] = 0; 36 } 37 } 38 return; 39 } 40 41 int main() 42 { 43 memset(vcolu,0,sizeof(vcolu)); 44 memset(ldown,0,sizeof(ldown)); 45 memset(rdown,0,sizeof(rdown)); 46 memset(ans,0,sizeof(ans)); 47 for(int i=1; i<=10; ++i) //预处理枚举n为1到10的答案 48 { 49 DFS(i,1); 50 } 51 while(cin>>n) 52 { 53 if(n==0) break; 54 cout<<ans[n]<<endl; 55 } 56 return 0; 57 }
以上是关于HDU2553 N皇后问题——DFS的主要内容,如果未能解决你的问题,请参考以下文章