题解 | #购物单#
购物单
https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4
#include <iostream> #include <vector> #include <unordered_map> using namespace std; int main() { int money, num; unordered_map<int, vector<int>> primary; cin >> money >> num; if (money <= 0 || num <= 0) { return 0; } money /= 10; // cin primary vector<int> price(num+1, 0), value(num+1, 0); for (int i = 1; i <= num; ++i) { int v, p, q; cin >> p >> v >> q; price[i] = p/10; value[i] = v*p; if (q == 0) { if (!primary.count(i)) { primary.insert({i, {0, 0}}); } } if (q > 0) { if (!primary.count(q)) { primary.insert({q, {i, 0}}); } else { if (primary[q][0] == 0) primary[q][0] = i; else primary[q][1] = i; } } } // bag vector<int> dp(money+1, 0); for (const auto pr: primary) { int id = pr.first; for (int j = money; j >= price[id]; --j) { int ap1 = pr.second[0], ap2 = pr.second[1]; dp[j] = max(dp[j], dp[j-price[id]]+value[id]); if (j >= price[ap1] + price[id]) { dp[j] = max(dp[j], dp[j-price[id]-price[ap1]]+value[id]+value[ap1]); } if (j >= price[ap2] + price[id]) { dp[j] = max(dp[j], dp[j-price[id]-price[ap2]]+value[id]+value[ap2]); } if (j >= price[ap1] + price[ap2] + price[id]) { dp[j] = max(dp[j], dp[j-price[id]-price[ap1]-price[ap2]]+value[id]+value[ap1]+value[ap2]); } } } cout << dp[money] << endl; return 0; }
关键点:
为了更方便主键没有附件填0,所以Price和value需要多申请一个,下标从1开始。
逆向是为了优先把price大的物品先放进去试试,如果正向的话,Price小的物品已经占据了该空间,导致price大的无法放入。
dp推导公式逆向时,不是跟前一个比是跟自己比(前一个更新永远比当前慢):dp[j] = max(dp[j], dp[j-price[i]]+value[i])