• Bugs Integrated, Inc.


    Bugs Integrated, Inc.

    给出一个(n imes m)的矩形网格图,给出其中K个障碍物的位置,求其中最多能摆的(2 imes 3)的矩形的个数,(nleq 150,mleq 10)

    注意到m的数据范围很小,在这里进行进制压缩,而n进行对每一行的处理,设(f[i][j])表示前i行第i行状态为j的方案数,注意到,(2 imes 3)的矩形可以有3个长度,于是仅靠二进制是不够表现状态的,于是j是一个三进制数表示,其中2表示这个格子控制下面的2格,1表示1格,0表示没有,不难有(2 imes 3)矩形为下图所示

    2 2
    1 1
    0 0
    
    1 1 1
    0 0 0
    
    

    不难得知最多只有(3^{10}=59049),显然是会超时的,于是考虑剪枝,首先预处理出每一行合法的用(3 imes 1,2 imes 1)的矩形填充的状态,这样的个数经过测试最多只有(1278)多个,所以这样枚举大概只有(1278^2 imes 150=244992600),显然还是会超时,于是转移的时候不能枚举非法状态,于是用dfs转移继续剪枝,所以每个状态下远远不会有(1278)个,而经过测试,无棋子的棋盘上一个状态可以更新的状态只有326个,所以时间复杂度估计也就只有(150 imes 1278 imes 326=62494200),应该是可以通过的。

    因为空间卡的太死,所以要滚动数组转移,具体实现看代码。

    参考代码:

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #define il inline
    #define ri register
    using namespace std;
    bool M[151][25];
    int base[20],x,m,f,a[200][2000],
        at[200],dp[2][60000],tot;
    il void read(int&);il int max(int,int);
    void dfs1(int,int),dfs2(int,int,int);
    int main(){
        int lsy;read(lsy),base[0]=1;
        for(int i(1);i<=19;++i)base[i]=base[i-1]*3;
        while(lsy--){
            int n,K,l;read(n),read(m),read(K);
            memset(M,1,sizeof(M)),memset(dp,-2,sizeof(dp));
            memset(at,0,sizeof(at)),dp[0][0]=0;
            for(int i(1),j,k;i<=K;++i)
                read(j),read(k),M[j][k-1]&=false;
            for(x=1;x<=n;++x)dfs1(0,0);++at[0];
            for(x=0;x<n;++x){
                for(l=1;l<=at[x];++l)
                    f=a[x][l],dfs2(0,0,0),
                        cout<<tot<<endl,tot&=0;
                memset(dp[x&1],-2,sizeof(dp[x&1]));
            }printf("%d
    ",dp[n&1][0]);
        }
        return 0;
    }
    il int max(int a,int b){
        return a>b?a:b;
    }
    void dfs2(int y,int e,int t){
        if(y>=m)return (void)(dp[(x+1)&1][e]=
                              max(dp[(x+1)&1][e],dp[x&1][f]+t));
        if(f/base[y]%3==2){
            if(M[x+1][y]&&M[x+1][y+1])
                dfs2(y+2,e+base[y]+base[y+1],t);
            return;
        }
        else if(f/base[y]%3==1){
            while(f/base[y]%3==1&&y<m)
                if(M[x+1][y])++y;
                else return;
            dfs2(y,e,t);return;
        }
        else{
            if(M[x+1][y]&&M[x+1][y+1]&&y+1<m)
                if(!(f/base[y+1]%3))
                    dfs2(y+2,e+base[y]*2+base[y+1]*2,t+1);
            if(M[x+1][y]&&M[x+1][y+1]&&M[x+1][y+2]&&y+2<m)
                if(!(f/base[y+1]%3)&&!(f/base[y+2]%3))
                    dfs2(y+3,e+base[y]+base[y+1]+base[y+2],t+1);
        }dfs2(y+1,e,t),++tot;
    }
    void dfs1(int y,int e){
        if(y==m)return (void)(a[x][++at[x]]=e);
        if(M[x][y]&&M[x][y+1]&&y+1<m){
            dfs1(y+2,e+base[y]+base[y+1]),
                dfs1(y+2,e+base[y]*2+base[y+1]*2);
            if(M[x][y+2]&&y+2<m)
                dfs1(y+3,e+base[y]+base[y+1]+base[y+2]);
        }dfs1(y+1,e);
    }
    il void read(int &x){
        x&=0;ri char c;while(c=getchar(),c<'0'||c>'9');
        while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
    }
    
    
  • 相关阅读:
    乱七八杂
    转化跟踪设置说明
    Photoshop图象切片保存为网页HTML(DIV+CSS布局)的方法
    HTTP 错误 403.14
    打开asp出现An error occurred on the server when processing the URL
    ADODB.Connection 错误 '800a0e7a'
    修改客户端连接的服务器IP地址(内部使用)
    关于云计算的10个常见问题解答
    云安全的11个挑战及应对策略
    如何鉴别一个区块链项目的真假?
  • 原文地址:https://www.cnblogs.com/a1b3c7d9/p/11013958.html
Copyright © 2020-2023  润新知