P1064 金明的预算方案 (背包)
Posted feiief
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1064 金明的预算方案 (背包)相关的知识,希望对你有一定的参考价值。
题解:
对每种主件的 附件的集合 进行一次 01 背包处理,就可以先求出 对于每一种主件包括其附件的组合中,每种花费的最大价值,对应不同的方案。
在对主件进行背包处理。
需要注意的是在对每个主件的附件进行处理时,要恰好花完价钱,否则方案数会非常多。
Code:
1 #include <bits/stdc++.h> 2 # define LL long long 3 using namespace std; 4 5 const int maxn=65; 6 int N, m; 7 8 struct Obj{ 9 int v,p,q; 10 }arr[maxn];; 11 Obj fujian[maxn][5]; //主件的附件信息 12 int fcnt[maxn]; //主件的附件个数 13 int f[33000]; //i价钱取得的最大价值 14 int V[maxn][5]; //主件的不同方案需要的价钱 15 int P[maxn][5]; //主件的不同方案获得的价值 16 int pcnt[maxn]; //各个主件的方案数 17 18 int main(){ 19 scanf("%d %d", &N, &m); 20 int a,b,c; 21 for(int i=1;i<=m;++i){ 22 scanf("%d %d %d", &a, &b, &c); 23 arr[i].v=a; 24 arr[i].p=b; 25 arr[i].q=c; 26 if(c>0){ 27 fcnt[c]++; 28 fujian[c][fcnt[c]].v=a; 29 fujian[c][fcnt[c]].p=b; 30 fujian[c][fcnt[c]].q=c; 31 } 32 } 33 for(int i=1;i<=m;++i){ //处理主件及其相应附件 34 if(arr[i].q==0){ 35 //只取主件 36 ++pcnt[i]; 37 V[i][pcnt[i]]=arr[i].v; 38 P[i][pcnt[i]]=arr[i].v*arr[i].p; 39 40 //考虑取不同附件 41 memset(f,-1,sizeof(f)); 42 f[0]=0; 43 for(int j=1;j<=fcnt[i];++j){ 44 for(int k=N-arr[i].v;k>=fujian[i][j].v;--k){ 45 if(f[k-fujian[i][j].v]!=-1) 46 f[k]=max(f[k],f[k-fujian[i][j].v]+fujian[i][j].v*fujian[i][j].p); 47 } 48 } 49 50 for(int j=0;j<=N-arr[i].v;++j){ //不同价钱对应的价值,即不同的方案 51 if(f[j]!=-1){ 52 ++pcnt[i]; 53 V[i][pcnt[i]]=arr[i].v+j; 54 P[i][pcnt[i]]=arr[i].v*arr[i].p+f[j]; 55 } 56 } 57 } 58 } 59 memset(f,0,sizeof(f)); 60 for(int i=1;i<=m;++i){ 61 if(arr[i].q==0){ 62 for(int j=N;j>=arr[i].v;--j){ 63 for(int k=1;k<=pcnt[i];++k){ 64 if(j>=V[i][k]){ 65 f[j]=max(f[j],f[j-V[i][k]]+P[i][k]); 66 } 67 } 68 } 69 } 70 } 71 printf("%d", f[N]); 72 return 0; 73 }
注意到题目说只有三种情况,每个主件可以有0个、1个或2个附件。
所以可以这样写:
1 #include <bits/stdc++.h> 2 # define LL long long 3 using namespace std; 4 5 const int maxn=65; 6 int N, m; 7 8 struct Obj{ 9 int v,p,q; 10 }arr[maxn];; 11 Obj fujian[maxn][5]; //主件的附件信息 12 int fcnt[maxn]; //主件的附件个数 13 int f[33000]; //i价钱取得的最大价值 14 int V[maxn][5]; //主件的不同方案需要的价钱 15 int P[maxn][5]; //主件的不同方案获得的价值 16 int pcnt[maxn]; //各个主件的方案数 17 18 int main(){ 19 scanf("%d %d", &N, &m); 20 int a,b,c; 21 for(int i=1;i<=m;++i){ 22 scanf("%d %d %d", &a, &b, &c); 23 arr[i].v=a; 24 arr[i].p=b; 25 arr[i].q=c; 26 if(c>0){ 27 fcnt[c]++; 28 fujian[c][fcnt[c]].v=a; 29 fujian[c][fcnt[c]].p=b; 30 fujian[c][fcnt[c]].q=c; 31 } 32 } 33 34 for(int i=1;i<=m;++i){ 35 if(arr[i].q==0){ 36 for(int j=N;j>=arr[i].v;--j){ 37 f[j]=max(f[j],f[j-arr[i].v]+arr[i].v*arr[i].p); 38 39 if(fcnt[i]>0 && j-arr[i].v-fujian[i][1].v>=0){ 40 f[j]=max(f[j],f[j-arr[i].v-fujian[i][1].v]+arr[i].v*arr[i].p+fujian[i][1].v*fujian[i][1].p); 41 } 42 if(fcnt[i]>1 && j-arr[i].v-fujian[i][2].v>=0){ 43 f[j]=max(f[j],f[j-arr[i].v-fujian[i][2].v]+arr[i].v*arr[i].p+fujian[i][2].v*fujian[i][2].p); 44 45 if(j-arr[i].v-fujian[i][2].v-fujian[i][1].v>=0){ 46 f[j]=max(f[j],f[j-arr[i].v-fujian[i][2].v-fujian[i][1].v]+arr[i].v*arr[i].p+fujian[i][2].v*fujian[i][2].p 47 +fujian[i][1].v*fujian[i][1].p); 48 } 49 } 50 } 51 } 52 } 53 printf("%d", f[N]); 54 return 0; 55 }
以上是关于P1064 金明的预算方案 (背包)的主要内容,如果未能解决你的问题,请参考以下文章