简单做个整理,是01背包问题的变形。
描述
总金额N,有M件商品
1.每个商品最多有2个附件,要购买附件必须先购买主件
2.每件商品按照v(价格),p(重要度),q(q=0主件,q>0是主件编号)提供
3.求最大满意度,
解析
谢谢牛友schwe1n的题解,这里做一点补充。
#include <iostream>
#include <vector>
using namespace std;
int main() {
int N, m;
cin >> N >> m;
vector<vector<int>> table(m, vector<int>(6,0)); //定义m行,6列的数组
// 输入数据(主件时放入编号为i,附件时放入编号为q)
for (int i = 0; i < m; i++){
int v, p, q;
cin >> v >> p >> q;
if (q == 0){
table[i][0] = v;
table[i][1] = v*p;
}
else if (table[q-1][2] == 0){
table[q-1][2] = v;
table[q-1][3] = v*p;
}
else if (table[q-1][4] == 0){
table[q-1][4] = v;
table[q-1][5] = v*p;
}
}
// 动态规划
vector<int> dp(N+1,0); // 注意是N+1容量,j才能取到N
for(int i = 0; i < m; ++i){
if (table[i][0] == 0) continue;
for(int j = N; j > 0; --j){
if(j >= table[i][0])
dp[j] = max(dp[j], dp[j - table[i][0]] + table[i][1]);
if(j >= table[i][0] + table[i][2])
dp[j] = max(dp[j], dp[j - table[i][0] - table[i][2]] + table[i][1] + table[i][3]);
if(j >= table[i][0] + table[i][4])
dp[j] = max(dp[j], dp[j - table[i][0] - table[i][4]] + table[i][1] + table[i][5]);
if(j >= table[i][0] + table[i][2] + table[i][4])
dp[j] = max(dp[j], dp[j - table[i][0] - table[i][2] - table[i][4]] + table[i][1] + table[i][3] + table[i][5]);
}
}
cout << dp[N] << endl;
return 0;
}
table表
table表存主件+附件
即 table[i][0]、table[i][2]、table[i][4]分别为主件和附件的容量
后 table[i][1]、table[i][3]、table[i][5]分别为主件和附件的满意度
dp数组
一维dp数组,与01背包类似,大小为总金额+1(即背包容量)
vector<int> dp(N+1,0);
遍历
遍历顺序:外层i遍历物品;内层j从N+1
开始倒序遍历容量。
递推公式
分四种情况
- 主件
- 主件 + 附件1
- 主件 + 附件2
- 主件 + 附件1 + 附件2
依次遍历判断,得到最大满意度