Description
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2553
DFS+回溯
低效:
#include<stdio.h> const int MAXN=20; void search(int cur); int n,tot,A[MAXN]; int main() { freopen("in.txt","r",stdin); int result[11]; for(n=1;n<=10;n++){ tot=0; search(0); result[n]=tot; } while(scanf("%d",&n)&&n) printf("%d\n",result[n]); return 0; } void search(int cur) { int i,j; if(cur==n)tot++; else for(i=0;i<n;i++){ int ok=1; A[cur]=i; for(j=0;j<cur;j++){ if( A[cur]==A[j] ||cur-A[cur]==j-A[j] ||cur+A[cur]==j+A[j] ){ok=0;break;} } if(ok)search(cur+1); } }
改进,减少循环次数:
#include<stdio.h> #include<memory.h> const int MAXN=30; void search(int cur); int n,tot,vis[3][MAXN]; int main() { // freopen("in.txt","r",stdin); int result[11]; for(n=1;n<=10;n++){ memset(vis,0,sizeof(vis)); tot=0; search(0); result[n]=tot; } while(scanf("%d",&n)&&n) printf("%d\n",result[n]); return 0; } 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]){ 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; } } }
因为数据较小,可直接打表水过:
#include<stdio.h> int main() { int n,a[11]={0,1,0,0,2,10,4,40,92,352,724}; while(scanf("%d",&n)&&n) printf("%d\n",a[n]); return 0; }