题解 AT4525 【Knapsack 1】
01背包板子题
其实就是背包问题。
一,顺推
1,状态定义
我们不妨设 $dp[i][j]$ 表示取完第i个物品后,背包装了重量j的物品时的最大价值。因而答案为 $dp[n][w]$。
2,状态转移方程
边界条件:
- $i <= 0 时 dp[i][j] = 0$
对于第i个物品,可以选择选或不选
选:$dp[i][j] = dp[i-1][j-w[i]] + v[i]$
不选时:$dp[i][j] = dp[i-1][j]$
再比较两种选择取个max值。
3,代码
自己写吧。。。
二,倒推
dp既可以顺推,也可以倒推。
1,状态定义
我们不妨设 $dp[i][j]$ 表示取完第i个物品后,背包装了重量j的物品时的最大价值。由于是倒推,从最后一个物品开始,往前推,因而答案为 $dp[1][w]$。
2,状态转移方程
边界条件:
- $i <= 0 时 dp[i][j] = 0$
对于第i个物品,可以选择选或不选
选:$dp[i][j] = dp[i+1][j-w[i]] + v[i]$
不选时:$dp[i][j] = dp[i+1][j]$
再比较两种选择取个max值。
3,代码
#include<iostream>
using namespace std;
int vi[200],w[100000+10];
long long dp[200][100000+1];
int main(){
int n,v;
cin>>n>>v;
for(int i = 1; i <= n; i++){
cin>>vi[i]>>w[i];
}
for(int i = n; i >= 1; i--){
for(int j = 1; j <= v; j++){
if(j < vi[i]){
dp[i][j] = dp[i+1][j];
}
else{
dp[i][j] =max(dp[i+1][j],dp[i+1][j-vi[i]] + w[i]);
}
}
}
cout<<dp[1][v];
return 0;
}
看懂了吗?希望对您有帮助。