洛谷 P1064 金明的预算方案

先把主件拆开。例如两个附件的物品,拆成只买主件、主+附1、主+附2、主+附1+附2这四种对于这个物品的选法。

然后跑类似普通背包的,ans[i][j]表示前i个物品用j的钱的最大收益。如果当前物品为附件则ans[i]直接从ans[i-1]复制,直接忽略当前物品。否则枚举当前物品的所有选法,ans[i][j]=max(ans[i-1][j],ans[i-1][j-v[i]]+val[i])更新。此处v[i]表示当前枚举到的对于当前物品的选法的总费用,val[i]表示当前枚举到的对于当前物品的选法的总价值。

错误记录(调至少半小时):

1.在当前物品为附件时,直接跳掉了,没有复制ans[i-1]的答案

2.在拆开物品的时候,某一行的v2[i]的push_back的元素中却出现了cost[...]

3.57行直接max(ans[i-1][k],ans[i-1][k-c2[i][j]]+v2[i][j]),把前面选法得到的好的答案丢了

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<vector>
 4 using namespace std;
 5 int cost[70],val[70],q[70];
 6 vector<int> c2[70],v2[70],s[70];
 7 int ans[62][32100];
 8 int n,m;
 9 int main()
10 {
11     int i,sz,j,k;
12     scanf("%d%d",&n,&m);
13     for(i=1;i<=m;i++)
14     {
15         scanf("%d%d%d",&cost[i],&val[i],&q[i]);
16         val[i]=val[i]*cost[i];
17         if(q[i]!=0)    s[q[i]].push_back(i);
18     }
19     for(i=1;i<=m;i++)
20         if(q[i]==0)
21         {
22             sz=s[i].size();
23             if(sz==0)
24             {
25                 c2[i].push_back(cost[i]);
26                 v2[i].push_back(val[i]);
27             }
28             else if(sz==1)
29             {
30                 c2[i].push_back(cost[i]);
31                 v2[i].push_back(val[i]);
32                 c2[i].push_back(cost[i]+cost[s[i][0]]);
33                 v2[i].push_back(val[i]+val[s[i][0]]);
34             }
35             else if(sz==2)
36             {
37                 c2[i].push_back(cost[i]);
38                 v2[i].push_back(val[i]);
39                 c2[i].push_back(cost[i]+cost[s[i][0]]);
40                 v2[i].push_back(val[i]+val[s[i][0]]);
41                 c2[i].push_back(cost[i]+cost[s[i][1]]);
42                 v2[i].push_back(val[i]+val[s[i][1]]);
43                 c2[i].push_back(cost[i]+cost[s[i][0]]+cost[s[i][1]]);
44                 v2[i].push_back(val[i]+val[s[i][0]]+val[s[i][1]]);
45             }
46         }
47 //    for(i=1;i<=m;i++)
48 //    {
49 //        for(int j=0;j<c2[i].size();j++)    printf("%d %d ",c2[i][j],v2[i][j]);
50 //        puts("");
51 //    }
52     for(i=1;i<=m;i++)
53     {
54         for(j=0;j<c2[i].size();j++)
55         {
56             for(k=c2[i][j];k<=n;k++)
57                 ans[i][k]=max(ans[i][k],max(ans[i-1][k],ans[i-1][k-c2[i][j]]+v2[i][j]));
58         }
59         for(k=0;k<=n;k++)
60             ans[i][k]=max(ans[i][k],ans[i-1][k]);
61     }
62     printf("%d",*max_element(ans[m]+1,ans[m]+n+1));
63     return 0;
64 }
posted @ 2017-11-08 15:23  hehe_54321  阅读(165)  评论(0编辑  收藏  举报
AmazingCounters.com