1. 程式人生 > >洛谷 P1064 金明的預算方案

洛谷 P1064 金明的預算方案

枚舉 tdi std sin clas 3.5 更新 例如 ans

先把主件拆開。例如兩個附件的物品,拆成只買主件、主+附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 }

洛谷 P1064 金明的預算方案