题解 P1064 【金明的预算方案】
大致思路
这个题给了主件,附件,很明显按照主件来分组,然后再转化为背包问题
各变量
int v[65],p[65],q[65],ty[65][65],dp[200005],temp[200005];
v为每个物品价格,p为重要度,q为是否为主件或从属主件的编号,ty为分的组,dp储存的状态,temp为暂存数组
分组部分代码
for(int i=1;i<=m;i++)
{
cin>>v[i]>>p[i]>>q[i];
if(q[i]!=0)
ty[q[i]][++ty[q[i]][0]]=i;
}
每个数组的第一个元素存该组的附件数量,数组的值存的是每个附件的下标。
最重要的部分
既然已经分了组,那么就可以先枚举每一个分的组。接下来就可以按照0-1背包的思路来做了。
for(int i=1;i<=m;i++)//按照编号来枚举
{
if(q[i]!=0)
continue;//如果枚举到附件就跳过
if(ty[i][0]!=0)//如果该主件有附件
{
for(int j=v[i];j<=n;j++)
temp[j]=dp[j];//将现在的每个状态暂时储存
for(int j=n;j>=v[i];j--)
dp[j]=dp[j-v[i]]+v[i]*p[i];//将每一个状态都更新为选了该主件的状态
for(int j=1;j<=ty[i][0];j++)
{
int x=ty[i][j];
for(int k=n;k>=v[x]+v[i];k--)
dp[k]=max(dp[k],dp[k-v[x]]+v[x]*p[x]);
}//0-1背包
for(int j=v[i];j<=n;j++)
dp[j]=max(dp[j],temp[j]);//比较选与不选的值谁更大
}
else//没有附件
{
for(int k=n;k>=v[i];k--)
dp[k]=max(dp[k],dp[k-v[i]]+v[i]*p[i]);//0-1背包
}
}
最后再输出就行了

浙公网安备 33010602011771号