zoukankan      html  css  js  c++  java
  • POJ 1084 Square Destroyer

    POJ_1084

        对于任意一个正方形,我们都至少要拿掉其中的一个火柴,于是如果构造一个行表示火柴、列表示正方形的矩阵,如果第i根火柴属于第j个正方形,那么g[i][j]=1,否则g[i][j]=0。这样这个问题就转化成了选取尽量少的行,使得每列至少有一个1,于是就可以用Dancing Links解决了。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXD 7710
    #define INF 0x3f3f3f3f
    int N, M, r[7][7], d[7][7], miss[70], ANS, vis[MAXD], CN;
    int size, U[MAXD], D[MAXD], L[MAXD], R[MAXD], C[MAXD], S[MAXD], H[MAXD];
    void prep(int n, int m)
    {
        int i;
        for(i = 0; i <= m; i ++)
        {
            U[i] = D[i] = i;
            R[i] = i + 1, L[i + 1] = i;
            S[i] = 0;    
        }
        memset(H, -1, sizeof(H[0]) * (n + 1));
    }
    void insert(int r, int c)
    {
        ++ size;
        C[size] = c, ++ S[c];
        D[size] = D[c], U[size] = c;
        U[D[c]] = size, D[c] = size;
        if(H[r] == -1) H[r] = L[size] = R[size] = size;
        else
        {
            L[size] = H[r], R[size] = R[H[r]];
            L[R[H[r]]] = size, R[H[r]] = size;
        }
    }
    void dor(int i, int &cnt)
    {
        for(int j = 0; j < N; j ++) if(!miss[++ cnt]) r[i][j] = cnt;
    }
    void doc(int i, int &cnt)
    {
        for(int j = 0; j <= N; j ++) if(!miss[++ cnt]) d[i][j] = cnt;    
    }
    int check(int x, int y, int n)
    {
        int i;
        for(i = 0; i < n; i ++) if(!r[x][y + i]) return 0;
        for(i = 0; i < n; i ++) if(!d[x + i][y]) return 0;
        for(i = 0; i < n; i ++) if(!r[x + n][y + i]) return 0;
        for(i = 0; i < n; i ++) if(!d[x + i][y + n]) return 0;
        return 1;
    }
    void place(int x, int y, int n, int id)
    {
        int i;
        for(i = 0; i < n; i ++) insert(r[x][y + i], id);
        for(i = 0; i < n; i ++) insert(d[x + i][y], id);
        for(i = 0; i < n; i ++) insert(r[x + n][y + i], id);
        for(i = 0; i < n; i ++) insert(d[x + i][y + n], id);    
    }
    void init()
    {
        int i, j, k, x, cnt = 0;
        scanf("%d%d", &N, &M);
        memset(miss, 0, sizeof(miss));
        for(i = 0; i < M; i ++)
            scanf("%d", &x), miss[x] = 1;
        memset(r, 0, sizeof(r));
        memset(d, 0, sizeof(d));
        cnt = 0;
        for(i = 0; i < N; i ++)
            dor(i, cnt), doc(i, cnt);
        dor(N, cnt);
        cnt = 0;
        prep(2 * N * (N + 1), N * N * N);
        size = N * N * N;
        for(k = 1; k <= N; k ++)
            for(i = 0; i < N; i ++)
                for(j = 0; j < N; j ++)
                    if(check(i, j, k)) place(i, j, k, ++ cnt);
        R[cnt] = 0, CN = cnt; 
    }
    int least()
    {
        int i, j, k, ans = 0;
        memset(vis, 0, sizeof(vis[0]) * (CN + 1));
        for(i = R[0]; i != 0; i = R[i])
            if(!vis[i])
            {
                ++ ans;
                for(j = D[i]; j != i; j = D[j])
                    for(k = R[j]; k != j; k = R[k]) vis[C[k]] = 1;
            }
        return ans;
    }
    void remove(int c)
    {
        int i;
        for(i = D[c]; i != c; i = D[i])
            R[L[i]] = R[i], L[R[i]] = L[i];    
    }
    void resume(int c)
    {
        int i;
        for(i = U[c]; i != c; i = U[i])
            R[L[i]] = L[R[i]] = i;
    }
    void dance(int dep)
    {
        if(R[0] == 0)
        {
            ANS = std::min(ANS, dep);
            return ;    
        }
        if(dep + least() >= ANS) return ;
        int i, j, t = INF, id;
        for(i = R[0]; i != 0; i = R[i])
            if(S[i] < t) t = S[i], id = i;
        for(i = D[id]; i != id; i = D[i])
        {
            remove(i);
            for(j = R[i]; j != i; j = R[j]) remove(j);
            dance(dep + 1);
            for(j = L[i]; j != i; j = L[j]) resume(j);
            resume(i);
        }
    }
    void solve()
    {
        ANS = INF;
        dance(0);
        printf("%d\n", ANS);
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            init();
            solve();
        }
        return 0;    
    }
  • 相关阅读:
    mysql practice
    image update to ubuntu18.04
    C++11 new feature
    bazel remote executor--- buildfarm( in docker)
    python3学习笔记13(数据结构)
    python3学习笔记12(变量作用域)
    python3学习笔记11(函数)
    jmeter 01 之beanshell preprocessor
    python3学习笔记10(迭代器和生成器)
    python3学习笔记十(循环语句)
  • 原文地址:https://www.cnblogs.com/staginner/p/2665608.html
Copyright © 2011-2022 走看看