1 8 5 0
1 92 10
主对角线
列数+行数(i+j)
副对角线
会发现对角线上上的数字都是相等的。所以每条对角线用一个标记变量记录状态就行了。比如一个n*n的网格用大小为2*n-1个的数组标记。如果当前格的坐标为i行j列的话。映射到主对角线就为j-i.但数组下标不能是负数。所以再加一个n-1就转化非负数了。如左图对应从左下到右上就为。0,1,2,3,4,5,6,7,8,9,10,11,12,13,14。副对角线就直接映射就行了。.这样就使判断是否同对角线简单多了。其次这题要记录答案。已计算过的数据直接输出答案不然会超时。
#include <stdio.h> #include<string.h> int l[29],r[29],row[15],ans[15],sum,n; //l标记主对角线。r标记副对角线。row标记列是否被访问 void dfs(int p)//p代表当前需放皇后行数 { int i; if(p==n)//如果每行都放有皇后(从0开始放到n-1行) { sum++;//方法数加1 return ; } for(i=0;i<n;i++)//对列进行搜索 { if(!row[i]&&!l[i-p+n-1]&&!r[i+p])//判断该列。所在主对角线。副对角线是否已有皇后 { row[i]=1; l[i-p+n-1]=1;//见上解释 r[i+p]=1; dfs(p+1);//继续深搜 row[i]=0;//回溯 l[i-p+n-1]=0; r[i+p]=0; } } } int main() { memset(ans,-1,sizeof ans); while(scanf("%d",&n),n) { if(ans[n]!=-1) { printf("%d\n",ans[n]); continue; } memset(l,0,sizeof l); memset(r,0,sizeof r); memset(row,0,sizeof row); sum=0; dfs(0);//从0行开始搜索 ans[n]=sum; printf("%d\n",sum); } return 0; }