先上代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| #include <iostream> #include <algorithm> using namespace std; int main() { int M,N; cin>>M>>N; int W[N],C[N];+_ int dp[N][M+1]; for (int i = 0; i < N; ++i) { cin>>W[i]>>C[i]; } for (int i = 0; i < N; ++i) { dp[i][0]=0; } for (int i = 1; i < M+1; ++i) { if (W[0]<=i)dp[0][i]=C[0]; else dp[0][i]=0; } for (int i = 1; i < N; ++i) { for (int j = 0; j < M+1 ;++j) { if (j<W[i]) { dp[i][j] = dp[i - 1][j]; } else { dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - W[i]] + C[i]); } } }
cout<<dp[N-1][M]; return 0; }
|
dp[i][j] 表示从下标为 0 ~ i 的物品里任意取,放进容量为 j 的背包,价值总和最大是多少。
每次放进一个物品,每次增加一个背包容量,当物品放不进背包(j<W[i])时,取放进物品前的最好值(即dp[i-1][j])。即在图中取上一格的值;
1
| if (j<W[i]) { dp[i][j] = dp[i - 1][j]; }
|
当物品可以放进背包时,考虑放与不放。
- 不放:价值取图中上一格的值(即
dp[i-1][j])。
- 放:价值取下面两者的和:
- 该物品的价值(即
C[i])。
- 先放进该物品后剩余的背包空间(
[j - W[i])与 不放该物品情况([i - 1]) 下的值(dp[i - 1][j - W[i])。后者是先前计算好的最优值,所以整体肯定是最优解。
1 2 3 4 5
| dp[i][j] = max( dp[i - 1][j], dp[i - 1][j - W[i]] + C[i] );
|