首页 > 代码库 > HDU4084 插头dp
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\n", (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;}
HDU4084 插头dp
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。