刷题-背包问题变形-购物单
作者:互联网
// 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; }
标签:满意度,背包,int,giftInfo,v0,编号,购物单,dp,刷题 来源: https://www.cnblogs.com/tiangaoyunsi/p/16127610.html