思路
多重限制条件的01背包,输出选取那几小组,可以开个bool数组记录选取物品时的状态,然后从最后一个物品往上找标记。
后记
这道题比赛的时候数据太水,简单排序选一件物品就行,看别人代码还有直接输出零过了。。。比赛结束1小时左右,加强数据了,还好提前过了 ^ _ ^
物品标记当时想错了,赛后看看学长代码真的强
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <vector>
#include <map>
#include <bitset>
#include <set>
#include <string.h>
#include <cmath>
#include <queue>
#include <algorithm>
#define N 40
#define ll long long
#define lowbit(a) a&(-a)
#define pb(a) push_back(a)
#define mk(a, b) make_pair(a, b)
#define mem(a, b) memset(a, b, sizeof(a))
#define read(a) scanf("%d", &a)
#define print(a) printf("%d\n", a)
using namespace std;
struct group{
int p, a, c, m, g;
}a[N];
// 也可以开4个数组存每个小组信息,因为没有问最大的分值
int dp[N][N][N][N];
bool vis[N][N][N][N][N];
int main(){
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int n, P, A, M, C, G;
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%d%d%d%d%d", &a[i].p, &a[i].a, &a[i].c, &a[i].m, &a[i].g);
}
scanf("%d%d%d%d", &P, &A, &C, &M);
for (int i = 0; i < n; ++i) {
for (int j = P; j >= a[i].p; --j) {
for (int k = A; k >= a[i].a; --k) {
for (int l = C; l >= a[i].c; --l) {
for (int r = M; r >= a[i].m; --r) {
if (dp[j - a[i].p][k - a[i].a][l - a[i].c][r - a[i].m] + a[i].g > dp[j][k][l][r]) {
dp[j][k][l][r] = dp[j - a[i].p][k - a[i].a][l - a[i].c][r - a[i].m] + a[i].g;
// 将当前状态标记
vis[i][j][k][l][r] = true;
}
}
}
}
}
}
vector<int> wu;
// 从最后一个物品向前找标记
for (int i = n - 1, j = P, k = A, l = C, r = M; i >= 0; --i) {
if (vis[i][j][k][l][r]) {
wu.push_back(i);
j -= a[i].p;
k -= a[i].a;
l -= a[i].c;
r -= a[i].m;
}
if (j < 0 || k < 0 || l < 0 || r < 0)
break;
}
if (wu.empty()) {
printf("%d\n", 0);
}else {
printf("%d\n", wu.size());
sort(wu.begin(), wu.end());
for (auto it : wu) {
printf("%d ", it);
}
printf("\n");
}
return 0;
}