您的位置:首页 > Web前端

codeforces 182E Wooden Fence 动态规划

2012-04-25 14:35 351 查看
http://www.codeforces.com/problemset/problem/182/E

给你n中篱笆,每种篱笆都有一个长和一个宽,设为a[i],b[i],再给你一个长度L

问用这些篱笆的长可以组成多少长度为 L 的漂亮的篱笆

漂亮的定义: 1、相邻的两个篱笆要属于不同的种类

2、 后一个篱笆的长必须等于前一个篱笆的宽

注意:一个篱笆的两个边长都可以作为长

因为所选的每个篱笆都有两种状态,一种是用a[i]作为长,一种是用b[i]作为长

所以可以设dp[i][j][0]表示组成i长度的篱笆,最后一个为第j个篱笆,且第j个篱笆用a[i]作为长的方案数

同样dp[i][j][1]表示第j个篱笆用b[i]作为长

有了状态,转移过程就不太难了 j的前面必须有一个篱笆的宽等于j的长时才能转移

转移的时候还要注意一个篱笆的两个边长相等的情况

每次按要求 更新dp[i][j][0]和dp[i][j][1]即可

最后的答案是所有dp[L][i][0]和dp[L][i][1]的和,当然如果a[i]==b[i],就只加一次

View Code

#include<cstdio>
#include<cstring>
const int mod = 1000000007;
int dp[3005][110][2];
int a[110],b[110];
int main()
{
int n,l,i,j,k;
while(scanf("%d%d",&n,&l)!=EOF)
{
for(i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
memset(dp,0,sizeof(dp));
for(i=1;i<=l;i++)
{
for(j=1;j<=n;j++)
{
if(a[j]==i) dp[i][j][0]++;
if(b[j]==i) dp[i][j][1]++;
}
}
for(i=1;i<=l;i++)
{
for(j=1;j<=n;j++)
{
for(k=1;k<=n;k++)
{
if(j==k) continue;
if(a[j]==a[k] && i>a[j] && dp[i-a[j]][k][1] ) dp[i][j][0]=(dp[i][j][0]+dp[i-a[j]][k][1])%mod;
if(a[j]==b[k] && i>a[j] && a[k]!=b[k] && dp[i-a[j]][k][0] ) dp[i][j][0]=(dp[i][j][0]+dp[i-a[j]][k][0])%mod;

if(b[j]==b[k] && i>b[j] && dp[i-b[j]][k][0] ) dp[i][j][1]=(dp[i][j][1]+dp[i-b[j]][k][0])%mod;
if(b[j]==a[k] && i>b[j] && a[k]!=b[k] && dp[i-b[j]][k][1] ) dp[i][j][1]=(dp[i][j][1]+dp[i-b[j]][k][1])%mod;
}
}
}
__int64 ans=0;
for(i=1;i<=n;i++)
{
ans+=dp[l][i][0]; ans%=mod;
if(a[i]!=b[i])
ans+=dp[l][i][1]; ans%=mod;
}
printf("%I64d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: