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
*/
#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
*/
相关文章推荐
- HDU 4802 && HDU 4803 贪心,高精 && HDU 4804 轮廓线dp && HDU 4805 计算几何 && HDU 4811 (13南京区域赛现场赛 题目重演A,B,C,D,J)
- HDU 4804 Campus Design 轮廓线DP
- hdu 4804 Campus Design 轮廓线dp
- Campus Design HDU - 4804 (状压dp,轮廓线dp)
- HDU 4804 Campus Design 轮廓线DP
- HDU 4804 轮廓线DP
- hdu 4804 Campus Design (2013 南京 轮廓线dp)
- HDU 4804 Campus Design 轮廓线DP
- 【HDU】5766 Filling【轮廓线dp+burnside引理】
- HDU 1992 Tiling a Grid With Dominoes(轮廓线dp || 插头dp 简讲)
- 插头dp入门 hdu 4804 + 5286
- HDU 4804 Campus Design(状压DP)
- HDU 4804 Campus Design(经典轮廓线问题扩展)
- HDU 4804 Campus Design(插头DP)
- hdu 4804 插头DP
- HDU 1693 Eat the Trees(轮廓线DP)
- hdu 4804 Campus Design 插头dp
- [HDU 5180]chess 组合+轮廓线状压dp
- HDU-1992-Tiling a Grid With Dominoes-4列n行的骨牌-轮廓线DP
- HDU 2167 Pebbles(轮廓线,状态压缩DP)