不使用第一个dim,直接用1dim的dp数组来做的,
是0-1背包问题的,做了些改动的,主要是多了附件,若是没有附件的话,就是标准的0-1背包问题的;
附件的处理是最重要的,用map记录了附件,通过map可以直接查询出每个主件包括的所有附件
在0-1背包的基础上,需要在第二层循环,加入附件的,然后看加入附件以后的收益,和之前的收益,拿到最大值就可以
#include<iostream>
#include<vector>
#include<unordered_map>
#include<algorithm>
using namespace std;
int main(void) {
/*
是0-1背包问题的,做了些改动的,主要是多了附件,若是没有附件的话,就是标准的0-1背包问题的;
附件的处理是最重要的,用map记录了附件,通过map可以直接查询出每个主件包括的所有附件
在0-1背包的基础上,需要在第二层循环,加入附件的,然后看加入附件以后的收益,和之前的收益,拿到最大值就可以
*/
int i, j, k, m, n, x, y, z, N, tmp;
cin>>N>>m;
N = N/10;
vector<vector<int>> arr(m, vector<int>(3, 0));
unordered_map<int, vector<int>> mp; // 用来保存每个附件
vector<int> fujian;
for(j = 0; j < m; j++) {
scanf("%d %d %d", &arr[j][0], &arr[j][1], &arr[j][2]);
arr[j][0] = arr[j][0] / 10;
if(arr[j][2]!=0) {
mp[arr[j][2] - 1].push_back(j);
}
}
vector<int> dp(N+1, -0xffffff);
dp[0] = 0; // 初始化最开始的数值到 0
for(i = 0; i < m; i++) { // 遍历每个物品,因dp不需要考虑第一个dim,所以这里没问题,否则需要另外修改的
fujian = mp[i]; // 拿出该主件对应的所有附件
if(arr[i][2]!=0) { // 附件直接跳过,下个循环内单独处理的
continue;
}
for(j = N; j >= arr[i][0]; j--) { // 遍历合适的体积-钱
dp[j] = max(dp[j], dp[j - arr[i][0]] + arr[i][0] * arr[i][1]); // 算加入主件或者不加入的最大收益
if(fujian.size() > 0) { // 附件的个数 >= 1
y = fujian[0]; // 拿出附件1的标号 index
if(j - arr[i][0] - arr[y][0] >= 0) // 加入两件的,主件和附件1,以及不加入的最大收益,实际的i需要+1,但是省略了第一个dim
dp[j] = max(dp[j], dp[j - arr[i][0] - arr[y][0]] + arr[i][0] * arr[i][1] + arr[y][0] * arr[y][1]);
}
if(fujian.size() > 1) { // 附件的个数 = 2
z = fujian[1]; // 拿出附件2的标号 index
if(j - arr[i][0] - arr[z][0] >= 0) // 加入两件的,主件和附件2,以及不加入的最大收益,实际的i需要+1,但是省略了第一个dim
dp[j] = max(dp[j], dp[j - arr[i][0] - arr[z][0]] + arr[i][0] * arr[i][1] + arr[z][0] * arr[z][1]);
if(j - arr[i][0] - arr[y][0] - arr[z][0] >= 0) // 加入三件的,主件和附件1和附件2,以及不加入的最大收益,实际的i需要+2,但是省略了第一个dim
dp[j] = max(dp[j], dp[j - arr[i][0] - arr[y][0] - arr[z][0]] + arr[i][0] * arr[i][1] + arr[y][0] * arr[y][1] + arr[z][0] * arr[z][1]);
}
}
}
vector<int>::iterator it = max_element(dp.begin(), dp.end());
cout<<it[0] * 10;
return 0;
}

京公网安备 11010502036488号