- 注意基本的背包问题的变化版本而已。
- 由于价格是10的整数倍,处理一下以降低空间/时间复杂度
- 并行判断技巧。(由于后三种情况是在放a的基础上,所以不满足的条件为 dp[i][j])
- 数组总要开大一个以及读取三元组的技巧
#include<bits/stdc++.h> using namespace std; int main(){ int N, m; cin>>N>>m; // 由于价格是10的整数倍,处理一下以降低空间/时间复杂度 N/= 10; //否则开出的DP将会非常的大,最后结果记得乘个10就行 //商品编号从1开始,所以要比既定目标大一个 vector<vector<int>> prices(60, vector<int>(3,0));// 价格 vector<vector<int>> priceMultiplyPriority(60, vector<int>(3,0)); // 重要程度 for(int i = 1; i<=m;i++){ int v, p,q; cin>>v>>p>>q; v /=10; p*= v; // 每件商品除以10减少复杂度,以及顺便把最后的权重算出来(就是两项的乘积) if(q==0){ prices[i][0] = v; // 录入主件的加个 priceMultiplyPriority[i][0] = p;//录入主件的权重 }else{ if(prices[q][1]==0){// 所属主键的第一个附件 prices[q][1] = v; priceMultiplyPriority[q][1] = p; }else{// 所属主键的第二个附件 prices[q][2] = v; priceMultiplyPriority[q][2] = p; } } } // 使用分组背包 vector<vector<int>> dp(m+1, vector<int>(N+1,0));// 同时包含了初始化 for(int i = 1; i<=m;i++){ for(int j = 1; j<=N;j++){// 平行比较,最大的就是最大的了。如果该产品没有附件的话,那就是0,并且不会影响结果。 int a = prices[i][0], b = priceMultiplyPriority[i][0]; int c = prices[i][1], d = priceMultiplyPriority[i][1]; int e = prices[i][2], f = priceMultiplyPriority[i][2]; //平行比较 dp[i][j] = j>=a ? max(dp[i-1][j-a]+b,dp[i-1][j]) : dp[i-1][j]; dp[i][j] = j>= (a + c) ? max(dp[i-1][j-a-c]+b+d,dp[i][j]) : dp[i][j]; dp[i][j] = j>= (a + e) ? max(dp[i-1][j-a-e]+b+f,dp[i][j]) : dp[i][j]; dp[i][j] = j>= (a + c + e)? max(dp[i-1][j-a-c-e]+b + d + f,dp[i][j]) : dp[i][j]; } } cout<<dp[m][N]*10<<endl; return 0; }