sicily 1346. 金明的预算方案

//NOIP2006的题目,在转移的时候主件有四种转移方法:不加附件,加两附件,加附件一或加附件二
#include<iostream> //分组背包问题
#include<cstring>
using namespace std;
struct node
{
int v,w;
}table[
62][10];
int n,m,v[62],p[62],q[62],len[62],dp[40000];
int main()
{
while(cin>>n>>m)
{
for(int i=1;i<=m;++i)
{
cin
>>v[i]>>p[i]>>q[i];
if(q[i]==0)
{
len[i]
=1;
table[i][
0].v=v[i];table[i][0].w=p[i]*v[i]; //单独主件,不加附件
}
else
len[i]
=0; //表明是附件
}
for(int i=1;i<=m;++i)
if(q[i]>0)
{
if(len[q[i]]==1) //当前主件内没有附件
{
table[q[i]][
1].v=table[q[i]][0].v+v[i]; //主件加附件一
table[q[i]][1].w=table[q[i]][0].w+v[i]*p[i];
len[q[i]]
=2;
}
else //当前主件内已有附件一
{
table[q[i]][
2].v=table[q[i]][0].v+v[i]; //主件加附件二
table[q[i]][2].w=table[q[i]][0].w+v[i]*p[i];

table[q[i]][
3].v=table[q[i]][1].v+v[i]; //主件加附件一和二
table[q[i]][3].w=table[q[i]][1].w+v[i]*p[i];
len[q[i]]
=4;
}
}
memset(dp,
0,sizeof(dp));
for(int i=1;i<=m;++i)
if(q[i]==0) //如果该物品是附件则跳过
{
for(int j=n;j>=table[i][0].v;--j) //table[i][0].v在(table[i][0].v-table[i][len[i]-1].v)中肯定是最小的
for(int k=0;k<len[i];++k)
if(j>=table[i][k].v)
{
dp[j]
=max(dp[j],dp[j-table[i][k].v]+table[i][k].w);
}
}
cout
<<dp[n]<<endl;
}
return 0;
}

posted on 2011-07-06 22:53  sysu_mjc  阅读(271)  评论(0编辑  收藏  举报

导航