您的位置:首页 > 其它

HDU 3033 I love sneakers! 分组背包+约束限制(每组至少取一个)。

2012-08-13 19:21 477 查看

注意至少取一个,仔细分析一下,此时光靠一个一维数组是不可以完成状态转移的,必须用二维数组或两个一维数组(滚动数组)。

建议多用二维数组,二维数组比较好理解,不容易出错,除非数据量太大,二维开不下。当然,如果对状态转移理解的比较深刻可以尝试着写成滚动数组。

先讲一讲二维数组的做法:

dp[i][j]表示进行到了第i组容量为j所装载的最大价值。

则dp[i][j]这个状态必须从dp[i-1][j-w[x]]+p[x](选了第1个第i组的物品),dp[i][j-w[x]]+p[x](已经选过第i组的物品,这次又选了第i组的物品),dp[i][j](不选这个物品);

所以状态转移方程为:

dp[i][j]=max(dp[i][j],max(dp[i][j-w[x]]+p[x],dp[i-1][j-w[x]]+p[x]));


二维数组版:

ViewCode

#include<stdio.h>
#include<string.h>
#include<algorithm>
usingnamespacestd;
#defineinf1<<29
intn,sum,m;
intdp[10003];
intz[101],w[101],p[101];
intmain()
{
inti,j,k;
while(~scanf("%d%d%d",&n,&sum,&m))
{
for(i=1;i<=n;i++)
scanf("%d%d%d",&z[i],&w[i],&p[i]);
intg1=0,g2=1;
for(i=0;i<=sum;i++)
dp[g1][i]=0;
for(k=1;k<=m;k++)
{
for(j=0;j<=sum;j++)
dp[g2][i]=-inf;
for(j=sum;j>=0;j--)
for(i=1;i<=n;i++)
if(z[i]==k)
{
if(w[i]<=j)
dp[g2][j]=max(dp[g2][j],max(dp[g2][j-w[i]]+p[i],dp[g1][j-w[i]]+p[i]));
}
g1=!g1;g2=!g2;
}
printf("%d\n",dp[g1][sum]);
}
return0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: