Hdu 4804 Campus Design

有一个 n×m(n100,m10) 的棋盘,除了一些不能被覆盖的位置外其他的地方用 1×2 1×1 的骨牌填满, 1×1 的骨牌使用次数在 [C,D] 之间。问满足条件的方案数 (mod109+7)


一个简单的插头dp入门题。

不能覆盖的地方可以视作必须放下 1×1 的骨牌并且不占使用的个数来简化代码。

因为直接列下状态数内存吃不消,用滚动数组优化即可


有的时候一些适当的注释能降低写代码的时候的脑力负担

#include<bits/stdc++.h>
using namespace std;

const int mod = 1e9+7;
char Map[112][12];
bool arr[112][12];
#define LL long long
int dp[2][1<<12][25];

inline int ge(int k,int j){return (k >> j) & 1;}
inline int sub(int k,int j){return k & (~(1<<j));}
inline int add(int k,int j){return k | (1<<j);}

int main(){
    int n,m,c,d;
    while(~scanf("%d %d %d %d",&n,&m,&c,&d)){
        memset(dp,0,sizeof(dp));
        for(int i = 1; i <= n;i++)
            scanf("%s",Map[i]);
        for(int i = 0;i <= n;i++){
            for(int j = 0;j < m;j++){
                arr[i][j] = (i>0) && (Map[i][j] == '1');
            }
        }
        int bnd = (1<<m) - 1;
        dp[0][bnd][0] = 1;
        for(int i = 1; i <= n;i++){
            for(int j = 0; j < m;j++){

                for(int k = 0 ; k <= bnd; k ++){
                    for(int lef = 0 ; lef <= d;lef++){
                        int &ndp = dp[1][k][lef];
                        if(arr[i][j]){ // can add
                            if(ge(k,j)){
                                (ndp += dp[0][sub(k,j)][lef] ) %= mod; // |
                                if(lef-1>=0) (ndp += dp[0][k][lef-1]) %= mod;  //. 
                                if(j && ge(k,j-1)) (ndp += dp[0][sub(k,j-1)][lef]) %= mod; //- 
                            }
                            else (ndp += dp[0][add(k,j)][lef])%=mod;    //empty
                        }
                        else if(ge(k,j)) (ndp += dp[0][k][lef])%=mod; //only have .
                    }
                }

                for(int k = 0 ; k <= bnd; k ++){
                    for(int lef = 0 ; lef <= d;lef++){
                        dp[0][k][lef] = dp[1][k][lef];
                        dp[1][k][lef] = 0;
                    }
                }
            }
        }
        int ans = 0;
        for(int lef = c ; lef <= d;lef++){
            (ans += dp[0][bnd][lef] ) %= mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值