zoukankan      html  css  js  c++  java
  • UVA 1603 Square Destroyer

    https://vjudge.net/problem/UVA-1603

    题意:

    一个由火柴棒组成的正方形网络

    现在拿走一些火柴

    问在剩下的火柴里还要最少拿走几根火柴 才能够破坏所有的正方形

    n=5,火柴棒最多60根,状态压缩

    我们先只考虑没有拿走火柴棒的网格图

    设base[i][j] 表示第i行第j列的正方形 需要火柴的状态

    设squ[i]表示编号为i的正方形 需要火柴的状态

    预处理出 边长为1的正方形

    然后枚举他要往右下延伸的长度

    然后枚举延伸之后的正方形的每个网格

    squ[i]^=base[][]

    1^1=0,如果一个火柴棒是两个小正方形的交接处,组成大的正方形之后,这个火柴棒不再参与构成正方形的边,正好异或掉

     

    然后迭代加深搜索

    估价函数:

    设一开始拿走一些火柴棒之后的网格图 有状态为S 的火柴棒

    枚举所有的正方形i

    如果squ[i]&s == squ[i] 说明在S状态下,正方形i还没有被破坏

    让s^=squ[i],need++

    即暂时破坏这个正方形,拿走这个正方形的所有火柴棒,算作一根火柴棒,继续枚举

    如果枚举完后,当前拿走的火柴棒+need>限制,剪枝

    因为所有的正方形都要被破坏,所以与枚举顺序无关

    #include<cstdio>
    
    using namespace std;
    
    typedef long long LL;
    
    int n,cnt,maxd,tot;
    
    LL bit[61];
    
    LL base[6][6],squ[56];
    
    int get_ud(int i,int j)
    {
        return (2*n+1)*(i-1)+j-1;
    }
    
    int get_lr(int i,int j)
    {
        return (2*n+1)*(i-1)+j+n-1;
    }
    
    void build()
    {
        cnt=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            {
                base[i][j]=0;
                base[i][j]|=bit[get_ud(i,j)]|bit[get_ud(i+1,j)];
                base[i][j]|=bit[get_lr(i,j)]|bit[get_lr(i,j+1)];
                squ[++cnt]=base[i][j];
            }
        for(int siz=2;siz<=n;siz++)
            for(int i=1;i+siz-1<=n;i++)
                for(int j=1;j+siz-1<=n;j++)
                {
                    squ[++cnt]=0;
                    for(int w=0;w<siz;w++)
                        for(int h=0;h<siz;h++)
                            squ[cnt]^=base[i+w][j+h];
                }
    }
    
    bool dfs(int d,LL state)
    {
        if(d==maxd) 
        {
            for(int i=1;i<=cnt;i++)
                if((squ[i]&state)==squ[i]) return false;
            return true;
        }
        LL s=state;
        int need=0,del=0;
        for(int i=1;i<=cnt;i++)
            if((squ[i]&s)==squ[i])
            {
                need++;
                s^=squ[i];
                if(!del) del=squ[i];
            }
        if(d+need>maxd) return false;
        for(int i=1;i<=tot;i++)
            if((del&bit[i-1])==bit[i-1])
                if(dfs(d+1,state^bit[i-1])) return true;
        return false;
    }
    
    int main()
    {
        int T;
        scanf("%d",&T);
        bit[0]=1;
        for(int i=1;i<=60;i++) bit[i]=bit[i-1]<<1;
        int m,x; LL state;
        while(T--)
        {
            scanf("%d",&n);
            tot=2*n*(n+1); state=bit[tot]-1;
            scanf("%d",&m);
            while(m--)
            {
                scanf("%d",&x);
                state^=bit[x-1];
            }
            build();
            for(maxd=0;;maxd++) 
             if(dfs(0,state)) break;
            printf("%d
    ",maxd);
        }
    }
  • 相关阅读:
    飞跃平野(sdut1124)
    背包
    sdut2193救基友记3(三维)
    hdu1542 Atlantis(矩阵面积的并)
    hdu1505City Game(扫描线)
    poj3468A Simple Problem with Integers(线段树的区域更新)
    hdu1166敌兵布阵&&hdu1754I Hate It(线段树入门)
    Biorhythms(中国剩余定理)
    Sequence(priority_queue)
    Message Flood(map)
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7670117.html
Copyright © 2011-2022 走看看