1. 程式人生 > 其它 >刷題-揹包問題變形-購物單

刷題-揹包問題變形-購物單

// https://www.nowcoder.com/practice/f9c6f980eeec43ef85be20755ddbeaf4
// 牛客-hw機考-HJ16 購物單

#include <iostream>
#include <vector>
using namespace std;

struct GiftInfo {
    int v {};             // 價格   表示該物品的價格     v < 10000
    int satisfaction  {}; // 滿意度 表示該物品的 價格*重要度
};

void Solution()
{
    int N, m;
    cin 
>> N >> m; // N為總錢數, m為希望購買的物品個數 // 定義[m+1][3] 記錄禮品資訊 /* [編號i物品][ {編號i主件價格和滿意度}, {編號i主件的附件1價格和滿意度}, {編號i主件的附件2價格和滿意度} ] */ vector<vector<GiftInfo>> giftInfo(m+1, vector<GiftInfo>(3, {0})); for (int i = 1; i <= m; ++i) {
int v, p, q; cin >> v >> p >> q; if (q == 0) { // 為編號i的主件資訊 giftInfo[i][0].v = v; giftInfo[i][0].satisfaction = v * p; } else { // 附件資訊 if (giftInfo[q][1].v == 0) { // 附件1不存在則填充到附件1中 giftInfo[q][1].v = v; giftInfo[q][
1].satisfaction = v * p; } else { // 已存在附件1則填充到附件2中 giftInfo[q][2].v = v; giftInfo[q][2].satisfaction = v * p; } } } // 降低時間複雜度 N總錢數為10的倍數 int totalAmount = N/10; // dp[m+1][N] 用來記錄編號從1~m物件下,在1~N下的當前最大滿意度 vector<vector<int>> dp(m+1, vector<int>(totalAmount+1, 0)); /* 狀態轉移方程 dp[i][j] = max(dp[i-1][j], dp[i-1][j-w[i]]+v[i]) 變形公式: dp[編號i物品下][當前錢數]的最大滿意度 = 當前錢數 >= 某價值 ? max(dp[上一編號i物品][當前錢數-某價值後]的最大滿意度 + 某價值下的滿意度 > dp[上一編號i物品][當前錢數]的最大滿意度) */ for (int i = 1; i <= m; ++i) { int v0 = giftInfo[i][0].v/10, p0 = giftInfo[i][0].satisfaction/10; int v1 = giftInfo[i][1].v/10, p1 = giftInfo[i][1].satisfaction/10; int v2 = giftInfo[i][2].v/10, p2 = giftInfo[i][2].satisfaction/10; for (int j = 1; j <= totalAmount; ++j) { dp[i][j] = j >= v0 ? max(dp[i-1][j-v0] +p0, dp[i-1][j]) : dp[i-1][j]; dp[i][j] = j >= (v0+v1) ? max(dp[i-1][j-v0-v1] +p0+p1, dp[i][j]) : dp[i][j]; dp[i][j] = j >= (v0+v2) ? max(dp[i-1][j-v0-v2] +p0+p2, dp[i][j]) : dp[i][j]; dp[i][j] = j >= (v0+v1+v2) ? max(dp[i-1][j-v0-v1-v2] +p0+p1+p2, dp[i][j]) : dp[i][j]; } } // 由於上面最大滿意進行了/10, 故需要*10還原 cout << dp[m][totalAmount]*10 <<endl; } int main() { Solution(); return 0; }