笔者训练了很久,但是没有怎么训练算法题目,基本都是思维题,导致邀请赛打铁,所以笔者准备在没有邀请赛名额的下半年训练点传统算法题目;
第一个要挑战的就是笔者之前一直没法理解的dp,距离上次看已经两个月了;
对于这个问题的思路也很简单:能装下这个物品的时候,比较价值之后选择装或者不装这个物品
不装的话则与前一个状态相同,装的话则改变状态,通俗的称作状态转移方程
我们用一个二维数组存储所有的状态,也就是代码中的“dp”数组;
得到的状态转移方程为
dp[i][j]=max(dp[i-1][j],dp[i-1][j-volume[i]]+price[i]);
volume可写成weight,price可写成value
kkt
问题描述
有 N 件物品和一个体积为 M 的背包。第 i 个物品的体积为 vi,价值为 wi。每件物品只能使用一次。
请问可以通过什么样的方式选择物品,使得物品总体积不超过 MM 的情况下总价值最大,输出这个最大价值即可。
输入格式
第一行输入两个正整数 N,M。(1≤N,M≤1000)
接下来 N行,每行输入两个整数 vi,wivi,wi。(0≤vi,wi≤1000)
输出格式
输出一个整数,表示符合题目要求的最大价值。
输入
4 5
1 2
2 4
3 4
4 5
输出
8
可以得到代码实现部分如下
void Refra1n()
{
int n,m;cin>>n>>m;
vector<vector<int>>dp(n+1,vector<int>(m+1,0));
vector<int>volume(n+1),price(n+1);
for(int i=1;i<=n;i++)
cin>>volume[i]>>price[i];
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
{
if(j<volume[i])
dp[i][j]=dp[i-1][j];
else
dp[i][j]=max(dp[i-1][j],dp[i-1][j-volume[i]]+price[i]);
}
cout<<dp[n][m]<<endl;
}
至于完全背包,因为物品可以拿多次,所以状态转移方程只需改为
dp[i][j]=max(dp[i-1][j],dp[i][j-volume[i]]+price[i]);
~~~~~~~~~~~~~~~~~~^
i-1改为i,因为这个物品可以重复拿
01背包与完全背包的DP算法解析
4129

被折叠的 条评论
为什么被折叠?



