Spoj 1771

来源:互联网 发布:数据库逻辑结构 编辑:程序博客网 时间:2024/05/19 12:41

题意:

           跟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 * COLUMNint 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;} 


原创粉丝点击