原题
在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上。
你的任务是,对于给定的N,求出有多少种合法的放置方法。
Input
共有若干行,每行一个正整数N≤10,表示棋盘和皇后的数量;如果N=0,表示结束。
Output
共有若干行,每行一个正整数,表示对应输入行的皇后的不同放置数量。
Sample Input
1
8
5
0
Sample Output
1
92
10
代码
第一种解法(其实两种差不多)
#include <bits/stdc++.h>
using namespace std;
int n,k, p[9999999], hash_[9999999],sum;
void queen(int ordinal){if (ordinal == n + 1){sum++;return;}else{for (int x = 1; x <= n; x++){bool flag = true;if (!hash_[x]){for (int pre = 1; pre < ordinal; pre++){if (abs(ordinal - pre) == abs(x - p[pre])){flag = false;break;}}if (flag){hash_[x] = 1;p[ordinal] = x;queen(ordinal + 1);hash_[x] = 0;}}}}
}int main()
{int a[10];for(int i=0;i<10;i++){sum=0;n=i+1;queen(1);a[i]=sum;}while(cin>>k,k)cout<<a[k-1]<<endl;
}
第二种解法
#include <bits/stdc++.h>
using namespace std;
int cnt,col[11],n; //cnt用来数当前 n*n 宫格所得的解的数目,col临时记录被占了的格子,n为输入的宫格边长
bool check(int column,int row){ //判断是否满足占格条件for(int i=0;i<row;i++){ //遍历所有行,判断是否有打破规则的占格if(col[i]==column||(abs(col[i]-column)==abs(i-row)))//由于col是存放第 i 行被占用的列的下标,所以col[i]==column就表示这列已经被占了,不满足规定,需要重新选择列//abs(col[i]-column)==abs(i-row)是判断是否在同一对角线的(两个列下标相减等于两个行下标相减),自行画图理解return false;}return true;
}
void queen(int r){if(r==n){ //如果达到最大行,获得一个解(因为如果某个解不可行是无法走到最大行的)cnt++; //解的数目增加return;}for(int column=0;column<n;column++){ //对列单独遍历if(check(column,r)){ //判断当前坐标是否符合“与其他棋子不同行不同列”,“与其他棋子不同对角线”的规定col[r]=column; //如果符合要求,那么就将当前行坐标对应的列坐标存入col里面(即存放棋子占用的格子的坐标)queen(r+1); //由于当前行已选择了一列占格,此时需要看看下一行满足条件的列}}
}int main(){int save[10]; //存放十以内 n*n宫格的解的个数for(int i=0;i<=10;i++){cnt=0; //初始化memset(col,0,sizeof(col)); //初始化col数组n=i; //计算 1-10 的解数queen(0); //深搜save[i]=cnt;}while(cin>>n,n){cout<<save[n]<<endl;}
}