题目:P1219 [USACO1.5]八皇后 Checker Challenge
题目大意: 在n*n的棋盘上放棋子,要求所有的棋子不在同一行,同一列和同一对角线上,问有多少种放法,并输出前三种情况。
解题思路: 假如我们放第i个棋子,这个棋子假设放在第i行,那么这个棋子要满足什么条件才可以放下去?是不是要满足棋子不在同一行,同一列和同一对角线上这一条件?那么我们如何得知是不是满足条件呢?很简单,用数组表示状态。我们用三个数组分别表示列(a)的状态,左下到右上的对角线(b)的状态,左上到右下的对角线(c)的状态。列很好表示,假如这个棋子放在了第i行第j列,只要将b[j]的值置为1即可,表示第j列已经放了棋子。我们再来看看左下到右上的对角线(b),我们可以发现左下到右上的对角线的i+j是一个固定值,我们只要把b[i+j]的值置为1即可,表示这条对角线已经有棋子放下。我们再来看看左上到右下的对角线(c),发现左上到右下的对角线的i-j+n是一个固定值,我们只要把c[i-j+n]的值置为1即可,表示这条对角线已经有棋子放下。
代码:
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn = 1000;
int n,a[maxn], diagonal1[maxn], diagonal2[maxn],col[maxn],sum;
void dfs(int index) {
if (index == n + 1) {
sum++;
if (sum <= 3) {
for (int i = 1; i <= n; i++) {
cout << a[i] << " ";
}
cout << endl;
}
return;
}
for (int i = 1; i <= n; i++) {
if (!col[i]&&(!diagonal1[index+i]&&!diagonal2[index-i+n])) {
col[i]=1;//表示的是列
diagonal1[i+index]=1;//表示的是左下到右上的对角线
diagonal2[index-i + n] = 1;//表示的是左上到右下的对角线;
a[index] = i;//放下棋子
dfs(index + 1);//递归回溯
a[index] = 0;
col[i] = 0;
diagonal1[i + index] = 0;
diagonal2[index-i + n] = 0;
}
}
}
int main() {
cin >> n;
dfs(1);
cout << sum << endl;
}