zoukankan      html  css  js  c++  java
  • HDU4084 插头dp

    题意:给定一个图,0是不能放的,然后现在有1X1和1X2方块,最后铺满该图,使得1X1使用次数在C到D之间,1X2次数随便,问有几种放法

    思路:插头DP或轮廓线,多加一维DP讨论就可以

       注意插头DP状态转移的是轮廓线,从左上开始处理,具体见代码注释

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    #define CLR(x, v) memset(x, v, sizeof x);
    #define PI(x) printf("%lld
    ", (ll)(x))
    const int mod = 1e9+7;
    int n,m,c,d,dp[2][1<<11][25];
    char ss[105][15];
    int main() {
           // freopen("in.txt","r",stdin);
        while(~scanf("%d%d%d%d",&n,&m,&c,&d)){
            int i,j;
            memset(dp,0,sizeof(dp));
            for(i = 0;i < n;i++){
                scanf("%s",ss[i]);
            
            }
            int pre=1,now=0;
            dp[now][(1<<m)-1][0]=1;//0行时初始化为上一层轮廓线占满了
    
    
            for(i = 0;i < n;i++){
                for(j = 0;j < m;j++){
                    swap(now, pre);
                    memset(dp[now], 0, sizeof(dp[now]));
                    for(int k = 0;k <= d;k++){
                    for(int used = 0;used <(1<<m);used++){
                        if(ss[i][j] == '1'){
                            if(used & (1<<j))
                            dp[now][used][k+1] = (dp[now][used][k + 1] + dp[pre][used][k]) % mod;//当(i,j)这点上面的点即相应轮廓线上点被覆盖了,则可以放1*1的矩形
                            if(j && (used & (1<<j)) && !(used & (1<<(j-1))))
                            dp[now][used|(1<<(j-1))][k] = (dp[now][used|(1<<(j-1))][k] + dp[pre][used][k])%mod;//当当前点上面的点被覆盖左边点未被覆盖则可以横放
                            dp[now][used^(1<<j)][k] = (dp[now][used^(1<<j)][k] + dp[pre][used][k])%mod;//当前点上面未被覆盖时不可竖放,未被覆盖则可以覆盖,两种情况都用此行代码表示
                        }
                        else{
                            if(used & (1<<j))
                            dp[now][used][k] = (dp[now][used][k] + dp[pre][used][k]) %mod;//当前点不能覆盖时,只有上面的点被覆盖了才有意义需要被转移,不然就空出一个点无法覆盖,没有转移价值
                        }
                    }
    
                    }
                }
            }
            int sum = 0;
            for(i = c;i <= d;i++){
               // cout<<i<<" "<<dp[pre][0][i]<<" "<<dp[now][0][i]<<endl;
                sum += dp[now][(1<<m)-1][i];
                sum %= mod;
            }
    
                cout<<sum<<endl;
        }
        return 0;
    }
  • 相关阅读:
    elasticsearch 索引清理脚本及常用命令
    git 快速入门及常见用法
    第01章-成本,你真的算对过吗?
    windows mysql安装及常用命令
    centos7 systemctl配置开机自启动服务
    python pip手动安装二进制包
    centos7使用nginx+uwsgi部署python django项目
    python json.loads()、json.dumps()和json.dump()、json.load()区别
    比阿里云快2倍的InfluxDB集群,我们开源了
    为什么是InfluxDB | 写在《InfluxDB原理和实战》出版之际
  • 原文地址:https://www.cnblogs.com/shimu/p/5811708.html
Copyright © 2011-2022 走看看