您的位置:首页 > 其它

hdu 4804 轮廓线dp

2014-03-18 22:09 330 查看
脑子不好使,dp理解起来有难度,特别是没讲解的时候。看了半天终于看懂别人的代码了。

#include<stdio.h>
#include<string.h>
const int N=102,M=11,mod=1e9+7;
int bt[M],cur;
int n,m,c,d;
char mp
[M];
int dp[2][1<<10][22];//第i个格子,前i个状态为j,有k个1*1的方案数

void update(int ns,int s,int nk,int k){//状态转移[s][k]->[ns][nk]
if(ns&bt[m])//如果第m+1位不是1,那么说明有空格没填充,不符合条件
dp[1-cur][ns^bt[m]][nk]=(dp[1-cur][ns^bt[m]][nk]+dp[cur][s][k])%mod;
}

int main(){
bt[0]=1;
for(int i=1;i<M;i++)
bt[i]=bt[i-1]*2;
while(~scanf("%d %d %d %d",&n,&m,&c,&d)){
for(int i=0;i<n;i++)
scanf("%s",mp[i]);
memset(dp,0,sizeof dp);
cur=0;
int state=bt[m]-1;
dp[0][state][0]=1;

for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(mp[i][j]=='0'){//不能放
for(int k=0;k<=d;k++)
for(int s=0;s<=state;s++)
if(dp[cur][s][k])
update((s<<1)^1,s,k,k);
}
else{//能放
for(int k=0;k<=d;k++)
for(int s=0;s<=state;s++)
if(dp[cur][s][k]){
update((s<<1),s,k,k);//不放
update((s<<1)^1,s,k+1,k);//放1*1
if(j&&(s&1)==0)//如果是第1列或左边不能放--不更新
update((s<<1)^3,s,k,k);//横放1*2
if(i&&(s&bt[m-1])==0)//如果是第1行或上边不能放--不更新
update((s<<1)^bt[m]^1,s,k,k);//竖放1*2
}
}
memset(dp[cur],0,sizeof dp[cur]);
cur=1-cur;
}
}
int ans=0;
for(int i=c;i<=d;i++)
ans=(ans+dp[cur][state][i])%mod;
printf("%d\n",ans);
}
return 0;
}
/*
s表示当前位置的前m位的状态,s<<1表示向下一个滚动一位,^1是放1*1,^3是横放1*2,^bt[m]^1是竖放2*1
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: