题意:
跟n皇后一样,就是有些地方已经放了皇后,且范围是n <= 50
我的模板从 fp_hzq神牛哪里学到的
他的博客: http://blog.csdn.net/fp_hzq/article/details/6797150
从他的博客学到很多东西
这道题与普通的精确覆盖不同,有些地方不用全部覆盖,只要覆盖行和列,对角线不用全部覆盖,
只要做一个约束条件,而我采用的判断是,当R[0] >2*n时就结束,意思是将行和列覆盖完就结束了,选取的列也是 <= 2 * n
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define N 55
#define ROW N * N
#define COLUMN N * 2 + (2 * N - 1) * 2 + 10
#define AREA ROW * COLUMN
int U[AREA], D[AREA], L[AREA], R[AREA], C[AREA];
int int P[AREA], X[AREA], Y[AREA];
int H[ROW], S[COLUMN], Q[ROW];
int e;
void init(int n, int m){
for(int i = 0; i <= n; i++) H[i] = -1;
for(int i = 0; i <= m; i++){
S[i] = 0;
U[i] = D[i] = i;
L[i+1] = i;
R[i] = i + 1;
}
R[e = m] = 0;
}
void remove(int c){
L[R[c]] = L[c]; R[L[c]] = R[c];
for(int i = D[c]; i != c; i = D[i])
for(int j = R[i]; j != i; j = R[j])
U[D[j]] = U[j], D[U[j]] = D[j], -- S[C[j]];
}
void resume(int c){
for(int i = U[c]; i != c; i = U[i])
for(int j = L[i]; j != i; j = L[j])
U[D[j]] = D[U[j]] = j, ++ S[C[j]];
L[R[c]] = R[L[c]] = c;
}
int n;
int Dance(int k){
if(R[0] > 2 * n){//(k >= n)
for(int i = 0; i < k; i++){
P[Y[Q[i]]] = X[Q[i]];
}
for(int i = 1; i <= n; i++) {
printf("%d",P[i]);
if(i != n) printf(" ");
}
printf("\n");
return 1;
}
int c, tmp = ROW;
for(int i = R[0]; i != 0; i = R[i])
if(i <= 2 * n) {//(i <= n)
if(tmp > S[i])
tmp = S[c = i];
} else {
break;
}
remove(c);
for(int i = D[c]; i != c; i = D[i]){
Q[k] = i;
for(int j = R[i]; j != i; j = R[j]) remove(C[j]);
if(Dance(k + 1)) return 1;
for(int j = L[i]; j != i; j = L[j]) resume(C[j]);
}
resume(c);
return 0;
}
void Link(int r,int c,int i, int j){
C[++e] = c; ++S[c];
Y[e] = i; X[e] = j;
D[e] = D[c]; U[D[c]] = e;
U[e] = c; D[c] = e;
if(H[r] < 0) H[r] = L[e] = R[e] = e;
else {
R[e] = R[H[r]];
L[R[H[r]]] = e;
L[e] = H[r];
R[H[r]] = e;
}
}
int maze[N][N];
int c[4];
void find(int x, int y, int n){
c[0] = x; c[1] = n + y;
c[2] = n * 2 + (x + y - 1);
x = n - x + 1;
c[3] = n * 2 + (2 * n - 1) + (x + y - 1);
}
int main(){
// freopen("in","r",stdin);
while(scanf("%d",&n) != -1){
memset(maze,0,sizeof(maze));
memset(ma,0,sizeof(ma));
int x, y;
x = n * n; y = 2 * n + (2 * n - 1) * 2;
init(x,y);
for(int i = 1; i <= n; i++){
int tmp;
scanf("%d",&tmp);
if(tmp == 0) continue;
maze[i][tmp] = 2;
int s = i + tmp;
for(int j = 1; j <= n; j++)
if(maze[i][j] ==0)
maze[i][j] = 1;
for(int j = 1; j <= n; j++)
if(maze[j][tmp] == 0)
maze[j][tmp] = 1;
for(x = 1; x <= n; x++){
y = s - x;
if(y < 1 || y > n) continue;
if(maze[x][y] == 0) maze[x][y] = 1;
}
s = tmp - i;
for(x = 1; x <= n; x++){
y = x + s;
if(y < 1 || y > n) continue;
if(maze[x][y] == 0) maze[x][y] = 1;
}
}
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(maze[i][j] != 1)
{
find(i, j, n);
for(int k = 0; k < 4; k++)
Link((i-1) * n + j,c[k],i,j);
}
Dance(0);
}
return 0;
}