您的位置:首页 > 其它

hdu4804Campus Design(轮廓线dp)

2016-08-08 22:17 134 查看
题目链接:点这里!!!

题意:给你一个n*m的矩阵(1<=n<=100,1<=m<=10),矩阵里面分为空格和障碍物两种,现在用1*2,2*1,1*1的地板去铺满整个矩阵,且1*1地板所有个数的取值在[c,d]之间(1<=c<=d<=20),问你一共有多少种方法铺满?

题解:

基础的轮廓线dp,分情况讨论清楚。

1、我们设dp[cur][g][k]为当前情况已用了g个1*1的板子枚举状态为k的方案数。

2、假设当前(i,j)是障碍物的话,说明我(i,j)这个点不用填东西,并且(i,j)是东西的。

3、假设当前(i,j)是空格的话,我们分情况考虑下:

(1)假设(i,j)我不填东西,说明(i-1,j)是有东西的。

(2)假设(i,j)我填1*1,说明(i-1,j)是有东西的。

(3)假设(i,j)我填(2*1),说明(i-1,j)是没有东西的。

(4)假设(i,j)我填(1*2),说明(i,j-1)是没有东西的,(i-1,j)是有东西的。

讨论完就ok啦!!!具体看代码!!

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<vector>
#include<bitset>
#include<set>
#include<queue>
#include<stack>
#include<map>
#include<cstdlib>
#include<cmath>
#define pb push_back
#define pa pair<int,int>
#define clr(a,b) memset(a,b,sizeof(a))
#define lson lr<<1,l,mid
#define rson lr<<1|1,mid+1,r
#define bug(x) printf("%d++++++++++++++++++++%d\n",x,x)
#define key_value ch[ch[root][1]][0]
#pragma comment(linker, "/STACK:102400000000,102400000000")
typedef long long LL;
const LL MOD = 1000000007;
const int N = 55;
const int maxn = 1e6+15;
const int letter = 130;
const int INF = 1e9;
const double pi=acos(-1.0);
const double eps=1e-10;
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int n,m,c,d,cur,tt;
char s[110][15];
LL dp[2][25][1<<12];
///当前阶段放了k个1*1的方案为多少
void update(int a,int b,int p,int q){
if(b&(1<<m)) dp[cur][p][b^(1<<m)]=(dp[cur][p][b^(1<<m)]+dp[1-cur][q][a])%MOD;
}
int main(){
while(~scanf("%d%d%d%d",&n,&m,&c,&d)){
clr(s,0);
for(int i=0;i<n;i++) scanf("%s",s[i]);
clr(dp,0);
cur=0;
dp[0][0][(1<<m)-1]=1ll;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
cur=cur^1;
clr(dp[cur],0);
if(s[i][j]=='1'){///empty
for(int g=0;g<=d;g++){
for(int k=0;k<(1<<m);k++){
update(k,k<<1,g,g);
update(k,(k<<1)|1,g+1,g);
if(i&&!(k&(1<<m-1))) update(k,(k<<1)^(1<<m)^1,g,g);
if(j&&!(k&1)) update(k,(k<<1)^3,g,g);
}
}
}
else {
for(int g=0;g<=d;g++)
for(int k=0;k<(1<<m);k++)
update(k,(k<<1)|1,g,g);
}
}
LL ans=0;
for(int i=c;i<=d;i++) ans=(ans+dp[cur][i][(1<<m)-1])%MOD;
printf("%I64d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: