AC_3. 完全背包问题
代码:
//完全背包 //区别:每件物品可以选择无限次 /* f[i]表示总体积是i的情况下,最大价值是多少 答案:result : max{f[0...m]} 转移,从前往后考虑每个物品 for(int i =0;i<N;i++) { for(int j = v[i];j <= m;j++)//从小到大模拟 j-v[i]是算过的 f[j-v[i]]表示考虑前i个物品,包括第i个物品的情况下, 体积是j-v[i]的最大价值,可能已经包含若干个第i个物品了 { f[j] = max(f[j],f[j-v[i]] + w[i]); } //假设考虑前i-1个物品之后,所有的f[j]都是正确的 //来证明考虑完第i个物品后,所有的f[j]也都是正确的 对于某个j而言,如果最优解包含k个v[i]: f[j - k * v[i]] f[j - k * v[i] - v[i]] + w[i] f[j - (k - 1) * v[i] - v[i]] + w[i] 包含1个v[i] ... f[j] f[j - v[i] + w[i]] //好理解 for(int j = m;j>=v[i];j--) { for(int k = 0;k*v[i]<=j;k++) { f[j] = max(f[j],f[j-k*v[i]]+k*w[i]); } } } */ #include<iostream> #include<cstring> #include<algorithm> using namespace std; int N, V;//物品数和背包容量 const int NUM = 1005; int dp[NUM]; int main() { cin >> N >> V; for (int i = 0; i < N; i++) { int v, w; cin >> v >> w; for (int j = v; j <= V; j++)//枚举所有的体积 dp[j] = max(dp[j], dp[j - v] + w); } cout << dp[V] << endl; return 0; }
//0 1 背包:从大到小枚举
//完全背包:从小到大枚举
比较好理解的一种方式:
#include<iostream> #include<cstring> #include<algorithm> using namespace std; int N, V;//物品数和背包容量 const int NUM = 1005; int dp[NUM]; int main() { cin >> N >> V; for (int i = 0; i < N; i++) { int v, w; cin >> v >> w; for (int j = V; j >= v; j--)//枚举所有的体积 { for (int k = 0; k*v <= j; k++)//看看每个体积下的价值最大是多少 { dp[j] = max(dp[j], dp[j - k*v] + k*w);//在计算的过程中每次存储最大价值 } } } cout << dp[V] << endl; return 0; }
以大多数人努力程度之低,根本轮不到去拼天赋~