DFS
Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64uDescription
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
题解:此题采用的是递归枚举法(回溯法)。本题采用逐行放置。要预先把合法的放置方法数保存起来
设皇后的编号依次为1,2,……,n,则可以认为第i个皇后必须摆放在第i行,然后枚举第一个皇后的位置进行回溯,若某一次发现某个皇后无法找到摆放位置则直接返回,如果所有皇后都可以找到摆放位置,则说明存在一种摆法满足要求,统计有多少种摆法即可。
思路:每行最多只能有一个皇后,所以用a[ ]表示行向量,搜索从第一个行向量开始
按行向量递增搜索,一直到最后一个行向量结束时得到一种放置方法,用b[]保存摆法。
按行向量递增搜索,一直到最后一个行向量结束时得到一种放置方法,用b[]保存摆法。
AC代码:
#include<stdio.h> #include<cstring> int vis[30][30]; int c[30]; int cur,tot; int n; void search(int cur) { if(cur==n) tot++; else for(int i=0; i<n; i++) { if(!vis[0][i]&&!vis[1][cur+i]&&!vis[2][cur-i+n]) { c[cur]=i; vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=1; search(cur+1); vis[0][i]=vis[1][cur+i]=vis[2][cur-i+n]=0; } } } int main() { int b[11]; for(n=1; n<=10; n++) { memset(vis,0,sizeof(vis)); tot=0; search(0); b[n]=tot; } int bn; while(scanf("%d",&bn)&&bn) { printf("%d ",b[bn]); } return 0; }
AC代码:
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 const int maxn=11; 5 int b[maxn],a[maxn],sum,n; 6 7 void dfs(int cur) 8 { 9 if(cur == n+1)//递归边界,就有一种摆法 10 sum++; 11 else 12 for(int j = 1; j <=n; j++) 13 { 14 int ok=1; 15 a[cur] = j;//尝试把第cur行的皇后放在第j列 16 for(int i = 1; i<cur; i++) //检查是否和前面的皇后冲突 17 if(a[i] == a[cur] || abs(i - cur) == abs(a[i] - a[cur])) 18 { 19 ok=0; 20 break; 21 } 22 if(ok) 23 dfs(cur+1);//如果合法,继续递归 24 } 25 } 26 27 int main() 28 { 29 for(int i = 1; i <=maxn; i++) 30 { 31 sum = 0; 32 n= i; 33 dfs(1); 34 b[i] = sum; 35 } 36 while(cin>>n && n) 37 cout<<b[n]<<endl; 38 return 0; 39 }
一不小心找到了一个超简单,投机取巧的方法。。。。因为n<=10。但是不能ac。
1 #include <cstdio> 2 main() 3 { 4 int n,a[13]={0,1,0,0,2,10,4,40,92,352,724,2680,14200}; 5 while(scanf("%d",&n)) 6 printf("%d ",a[n]); 7 }