牛客网多校训练第三场 A - PACM Team(01背包变形 + 记录方案)
链接:
https://www.nowcoder.com/acm/contest/141/A
题意:
有n(1≤n≤36)个物品,每个物品有四种代价pi,ai,ci,mi,价值为gi(0≤pi,ai,ci,mi,gi≤36),
求四种代价分别不超过P,A,C,M(0≤P,A,C,M≤36)的条件下能获得的最大价值,输出所选择的物品。
分析:
01背包的思路,只是代价多了几个而已,数组开多几维就好了。
可以用vis[i][p][a][c][m]来表示在四种代价分别为p,a,c,m的状态下是否用第i件物品更新过,
从而实现记录方案的目的,详见代码。
代码:
1 #include <cstdio> 2 #include <vector> 3 using namespace std; 4 5 const int UP = 36 + 1; 6 int P, A, C, M; 7 int p[UP], a[UP], c[UP], m[UP], g[UP]; 8 int d[UP][UP][UP][UP]; 9 bool vis[UP][UP][UP][UP][UP]; 10 11 int main() { 12 int n; 13 scanf("%d", &n); 14 for(int i = 0; i < n; i++) 15 scanf("%d%d%d%d%d", &p[i], &a[i], &c[i], &m[i], &g[i]); 16 scanf("%d%d%d%d", &P, &A, &C, &M); 17 18 for(int i = 0; i < n; i++) { 19 for(int pp = P; pp >= p[i]; pp--) { 20 for(int aa = A; aa >= a[i]; aa--) { 21 for(int cc = C; cc >= c[i]; cc--) { 22 for(int mm = M; mm >= m[i]; mm--) { 23 if(d[pp][aa][cc][mm] < d[pp-p[i]][aa-a[i]][cc-c[i]][mm-m[i]] + g[i]) { 24 d[pp][aa][cc][mm] = d[pp-p[i]][aa-a[i]][cc-c[i]][mm-m[i]] + g[i]; 25 vis[i][pp][aa][cc][mm] = true; 26 } 27 } 28 } 29 } 30 } 31 } 32 33 vector<int> ans; 34 for(int i = n-1; i >= 0; i--) { 35 if(!vis[i][P][A][C][M]) continue; 36 ans.push_back(i); 37 P -= p[i]; A -= a[i]; C -= c[i]; M -= m[i]; 38 } 39 40 printf("%d\n", ans.size()); 41 if(ans.size()) { 42 printf("%d", ans[0]); 43 for(int i = 1; i < ans.size(); i++) printf(" %d", ans[i]); 44 } 45 printf("\n"); 46 return 0; 47 }