赞
踩
确定状态表示 -> dp[i][j]
的含义
dp[i][j]
:从前i
个物品中挑选,总体积不超过j
,所有选法中,能挑选出来的最大价值dp[i][j]
:从前i
个物品中挑选,总体积恰好等于j
,所有选法中,能挑选出来的最大价值推导状态转移方程:根据最后一个位置的情况,分情况讨论
不要求恰好装满:j - v[i] >= 0
是为了确保背包此时容量足够塞下当前物品
要求恰好装满:dp[i][j] == -1
表示没有这种情况,即此时总体积凑不到j
初始化:
vector<vector<int>> dp(n + 1, vector<int>(V + 1))
-1
确定填表顺序:从上往下,从左往右
确定返回值:
dp[n][V]
dp[n][V] == -1 ? 0 : dp[n][V]
每次填值,只依赖上一行及左边列的值
可以一个一维数组就优化掉此问题
操作
j
的遍历顺序注意:不要去强行解释优化后的妆台表示以及状态转移方程,费时费力还没啥意义
// v1.0 int main() { int n = 0, V = 0; cin >> n >> V; vector<int> v(n + 1), w(n + 1); for(int i = 1; i <= n; i++) { cin >> v[i] >> w[i]; } vector<vector<int>> dp(n + 1, vector<int>(V + 1)); // Q1 for(int i = 1; i <= n; i++) { for(int j = 1; j <= V; j++) { dp[i][j] = dp[i - 1][j]; if(j >= v[i]) { dp[i][j] = max(dp[i][j], dp[i][j - v[i]] + w[i]); } } } cout << dp[n][V] << endl; // Q2 dp.resize(n +1, vector<int>(V + 1)); for(int i = 1; i <= V; i++) { dp[0][i] = -1; } for(int i = 1; i <= n; i++) { for(int j = 0; j <= V; j++) // 下标从0开始 { dp[i][j] = dp[i - 1][j]; if(j >= v[i] && dp[i][j - v[i]] != -1) { dp[i][j] = max(dp[i][j], dp[i][j - v[i]] + w[i]); } } } cout << (dp[n][V] == -1 ? 0 : dp[n][V]) << endl; return 0; } -------------------------------------------------------------------------- // v2.0 滚动数组优化 int main() { int n = 0, V = 0; cin >> n >> V; vector<int> v(n + 1), w(n + 1); for(int i = 1; i <= n; i++) { cin >> v[i] >> w[i]; } vector<int> dp(V + 1); // Q1 for(int i = 1; i <= n; i++) { for(int j = v[i]; j <= V; j++) { dp[j] = max(dp[j], dp[j - v[i]] + w[i]); } } cout << dp[V] << endl; // Q2 dp.resize(V + 1); for(int i = 1; i <= V; i++) { dp[i] = -1; } for(int i = 1; i <= n; i++) { for(int j = v[i]; j <= V; j++) { if(dp[j - v[i]] != -1) { dp[j] = max(dp[j], dp[j - v[i]] + w[i]); } } } cout << (dp[V] == -1 ? 0 : dp[V]) << endl; return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。