牛客网多校训练第三场 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 }

 

posted @ 2018-08-13 21:37  Ctfes  阅读(201)  评论(0编辑  收藏  举报