• poj1084Square Destroyer(LDX解重复覆盖)


    题目请戳这里

    题目大意:给一个n*n的用单位长度的木棍拼起来的网格图,给每个木棍按图示编号,编号范围1~2*n*(n+1).现在已知图中已经去掉了k个木棍,求还要至少去掉几根木棍能使网格图中不存在正方形.即破坏图中所有的正方形.n不超过5.

    题目分析:n太小了啦,直接爆搜!dancing links优化之.将之转化成一个重复覆盖的模型.

    n*n的完全网格图中存在n*(n+1)*(2*n+1)/6个正方形.给每一个编号,然后小木棍的编号图中给了,就按那个来.然后小木棍为行,正方形为列,建图.

    注意题目已经给定的k个木棍要去掉.首先那k个木棍覆盖的正方形是不用建图的,然后那k个表头也要删掉.

    然后关于木棍编号破坏的正方形的关系.好像很复杂的样子,不过因为n太小了,然后我就打表了大笑..不过好难数,数了一晚上....哭

    正方形编号从1~n*(n+1)*(2*n+1)/6,顺序按边长递增从左上角到右下角.

    详情请见代码:

    #include <iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 6;
    const int M = 4000;//3300
    const int NM = 56;//最大正方形个数
    int n,K,num,ans;
    int h[M],s[M],u[M],d[M],l[M],r[M],col[M];
    bool flag[NM],vis[NM];
    int stk[NM];
    int table[5][61][NM] = {
    {
        {0},{1,1},{1,1},{1,1},{1,1},
    },
    {   {0},{2,1,5},{2,2,5},{2,1,5},{2,1,2},{2,2,5},{2,1,3},
        {2,2,4},{2,3,5},{2,3,4},{2,4,5},{2,3,5},{2,4,5},
    },
    {   {0},{3,1,10,14},{4,2,10,11,14},{3,3,11,14},{3,1,10,14},
        {3,1,2,11},{3,2,3,10},{3,3,11,14},{3,1,4,12},{4,2,5,12,13},
        {3,3,6,13},{4,4,10,12,14},{4,4,5,11,13},{4,5,6,10,12},
        {4,6,11,13,14},{3,4,7,10},{4,5,8,10,11},{3,6,9,11},
        {3,7,12,14},{3,7,8,13},{3,8,9,12},{3,9,13,14},
        {3,7,12,14},{4,8,12,13,14},{3,9,13,14},
    },
    {   {0},{4,1,17,26,30},{6,2,17,18,26,27,30},{6,3,18,19,26,27,30},{4,4,19,27,30},
        {4,1,17,26,30},{4,1,2,18,27},{4,2,3,17,19},{4,3,4,18,26},{4,4,19,27,30},
        {4,1,5,20,28},{5,2,6,20,21,29},{5,3,7,21,22,28},{4,4,8,22,29},
        {6,5,17,20,26,28,30},{6,5,6,18,21,27,29},{6,6,7,17,19,20,22},{6,7,8,18,21,26,28},{6,8,19,22,27,29,30},
        {4,5,9,17,23},{6,6,10,17,18,23,24},{6,7,11,18,19,24,25},{4,8,12,19,25},
        {6,9,20,23,26,28,30},{6,9,10,21,24,27,29},{6,10,11,20,22,23,25},{6,11,12,21,24,26,28},{6,12,22,25,27,29,30},
        {4,9,13,20,26},{5,10,14,20,21,27},{5,11,15,21,22,26},{4,12,16,22,27},
        {4,13,23,28,30},{4,13,14,24,29},{4,14,15,23,25},{4,15,16,24,28},{4,16,25,29,30},
        {4,13,23,28,30},{6,14,23,24,28,29,30},{6,15,24,25,28,29,30},{4,16,25,29,30},
    },
    {   {0},
        {5,1,26,42,51,55},{8,2,26,27,43,44,51,52,55},{9,3,27,28,42,43,44,51,52,55},{8,6,4,28,29,43,44,51,52,55},{5,5,29,44,52,55},
        {5,1,26,42,51,55},{5,1,2,27,43,52},{5,2,3,26,28,44},{5,3,4,27,29,42},{5,4,5,28,43,51},{5,5,29,44,52,55},
        {5,1,6,30,45,53},{8,2,7,30,31,45,46,53,54},{9,3,8,31,32,45,46,47,53,54},{8,4,9,32,33,46,47,53,54},{5,5,10,33,47,54},
        {8,6,26,30,42,45,51,53,55},{8,6,7,27,31,43,46,52,54},{8,7,8,26,28,30,32,44,47},{8,8,9,27,29,31,33,42,45},{8,9,10,28,32,43,46,51,53},{8,10,29,33,44,47,52,54,55},
        {5,6,11,26,34,48},{8,7,12,26,27,34,35,48,49},{9,8,13,27,28,35,36,48,49,50},{8,9,14,28,29,36,37,49,50},{5,10,15,29,37,50},
        {9,11,30,34,42,45,48,51,53,55},{9,11,12,31,35,43,46,49,52,54},{9,12,13,30,32,34,36,44,47,50},{9,13,14,31,33,35,37,42,45,48},{9,14,15,32,36,43,46,49,51,53},{9,15,33,37,44,47,50,52,54,55},
        {5,11,16,30,38,42},{8,12,17,30,31,38,39,42,43},{9,13,18,31,32,39,40,42,43,44},{8,14,19,32,33,40,41,43,44},{5,15,20,33,41,44},
        {8,16,34,38,45,48,51,53,55},{8,16,17,35,39,46,49,52,54},{8,17,18,34,36,38,40,47,51},{8,18,19,35,37,39,41,45,48},{8,19,20,36,40,46,49,51,53},{8,20,37,41,47,50,52,54,55},
        {5,16,21,34,45,51},{8,17,22,34,35,45,46,51,52},{9,18,23,35,36,45,46,47,51,52},{8,19,24,36,37,46,47,51,52},{5,20,25,37,47,52},
        {5,21,38,48,53,55},{5,21,22,39,49,54},{5,22,23,38,40,50},{5,23,24,39,41,48},{5,24,25,40,49,53},{5,25,41,50,54,55},
        {5,21,38,48,53,55},{8,22,38,39,48,49,53,54,55},{9,23,39,40,48,49,50,53,54,55},{8,24,40,41,49,50,53,54,55},{5,25,41,50,54,55},
    }
    };
    
    void init()
    {
        int i,c;
        memset(h,0,sizeof(h));
        memset(s,0,sizeof(s));
        c = n * (n + 1) * (2 * n + 1)/6;
        for(i = 0;i <= c;i ++)
        {
            u[i] = d[i] = i;
            l[i] = (i + c)%(c + 1);
            r[i] = (i + 1)%(c + 1);
        }
        num = c + 1;
    }
    void ins(int i,int j)
    {
        if(h[i])
        {
            r[num] = h[i];
            l[num] = l[h[i]];
            l[r[num]] = r[l[num]] = num;
        }
        else
        {
            h[i] = num;
            l[num] = r[num] = num;
        }
        s[j] ++;
        u[num] = u[j];
        d[num] = j;
        d[u[j]] = num;
        u[j] = num;
        col[num] = j;
        num ++;
    }
    void del(int c)
    {
        for(int i = d[c];i != c;i = d[i])
            l[r[i]] = l[i],r[l[i]] = r[i];
    }
    void recover(int c)
    {
        for(int i = u[c];i != c;i = u[i])
            l[r[i]] = r[l[i]] = i;
    }
    int A()
    {
        int i,j,k,ret;
        ret = 0;
        memset(vis,false,sizeof(vis));
        for(i = r[0];i;i = r[i])
        {
            if(vis[i] == false)
            {
                ret ++;
                vis[i] = true;
                for(j = d[i];j != i;j = d[j])
                    for(k = r[j];j != k;k = r[k])
                        vis[col[k]] = true;
            }
        }
        return ret;
    }
    void dfs(int k)
    {
        if(k + A() >= ans)
            return;
        if(!r[0])
        {
            ans = min(ans,k);
            return ;
        }
        int mn = M;
        int c,i,j;
        for(i = r[0];i;i = r[i])
        {
            if(s[i] < mn)
            {
                mn = s[i];
                c = i;
            }
        }
        for(i = d[c];i != c;i = d[i])
        {
            del(i);
            for(j = r[i];j != i;j = r[j])
                del(j);
            dfs(k + 1);
            for(j = l[i];j != i;j = l[j])
                recover(j);
            recover(i);
        }
    }
    
    void build()
    {
        scanf("%d",&n);
        memset(flag,false,sizeof(flag));
    
        scanf("%d",&K);
        int i,j;
        for(i = 1;i <= K;i ++)
        {
            scanf("%d",&stk[i]);
            for(j = 1;j <= table[n - 1][stk[i]][0];j ++)
                flag[table[n - 1][stk[i]][j]] = true;
        }
        init();
        for(i = 1;i <= (n + 1) * n * 2;i ++)
        {
            for(j = 1;j <= table[n - 1][i][0];j ++)
                if(flag[table[n - 1][i][j]] == false)
                    ins(i,table[n - 1][i][j]);
        }
        int nmgb = 0;
        for(i = 1;i <= n * (n + 1) * (n * 2 + 1)/6;i ++)
            if(flag[i])
                l[r[i]] = l[i],r[l[i]] = r[i];
    }
    void fuck()
    {
        ans = M;
        dfs(0);
        printf("%d
    ",ans);
    }
    int main()
    {
        int t;scanf("%d",&t);
        while(t --)
        {
            build();
            fuck();
        }
        return 0;
    }
    //244K	0MS
    
    


  • 相关阅读:
    本题要求两个给定正整数的最大公约数和最小公倍数。
    习题4-6 水仙花数 (20 分)
    习题4-5 换硬币 (20 分)
    习题4-4 特殊a串数列求和 (20 分)
    练习4-11 统计素数并求和 (20 分)
    一分钟玩转 Spring IoC
    vue 项目如何使用animate.css
    web前端自定义函数工具库
    React Context 理解和使用
    jQuery的链式编程风格
  • 原文地址:https://www.cnblogs.com/riasky/p/3481929.html
Copyright © 2020-2023  润新知