原文地址:http://acm.timus.ru/problem.aspx?space=1&num=1034
题目
一个 N×N(N≤50) 的棋盘上有 N 个皇后。我们认为这个棋盘的皇后摆放方案是和平的仅当没有一个皇后与其他皇后在同一行、同一列、同一斜线上(因为可以互相攻击)。你需要找出一些方案使得对于一个和平的摆放,只改变其中三个皇后的位置,新的摆放仍然是和平的。
输入
输入第一行一个整数
接下来
N
行每行2个整数
输出
输出一行一个整数,表示有多少种改变皇后位置的方案满足条件(所有皇后是等价的,如果你只交换2个皇后,不算一种新方案)。
样例输入
4
2 1
1 3
3 4
4 2
样例输出
0
题解
考虑到每行每列都有一个皇后,改变3个皇后的位置的话,如果全改到一行里肯定是不合法的,因此我们只横向移动皇后(即改变y坐标,当然你只纵向移动也没问题,我们这里规定横向移动,这样竖向的移动其实是没有意义的,比如2行皇后调到4行,4行的皇后调到了2行【当然调到其他地方去就冲突不合法了】,相当于2行和4行的皇后横向调整)。然后因为N很小,所以我们枚举3个皇后,交换她们的横坐标(y坐标),这样横纵方向都是满足条件的,只要再判断斜方向是否冲突即可。
#include <cstdio>
#include <cstring>
#define FOR(i,j,k) for(i=j;i<=k;++i)
#define rep(i,j,k) for(i=j;i<k;++i)
int col[64], rb[256], rt[256];
int n;
inline void roll(int i, int j, int k) {
int a = col[i], b = col[j], c = col[k];
col[i] = b; col[j] = c; col[k] = a;
}
inline bool judge() {
int i;
memset(rb, 0, sizeof rb);
memset(rt, 0, sizeof rt);
FOR(i,1,n) {
if (rb[i + col[i] + 128]) return false;
if (rt[i - col[i] + 128]) return false;
rb[i + col[i] + 128] = true;
rt[i - col[i] + 128] = true;
}
return true;
}
int main() {
int x, y, i, j, k, s = 0;
scanf("%d", &n);
FOR(i,1,n) scanf("%d%d", &x, &y), col[x] = y;
FOR(i,1,n) rep(j,1,i) rep(k,1,j) {
roll(i, j, k);
if (judge()) ++s;
roll(i, j, k);
if (judge()) ++s;
roll(i, j, k);
}
printf("%d\n", s);
return 0;
}