[动态规划 01背包详解]洛谷P2871 [USACO07DEC]手链Charm Bracelet

第一篇博客 请多关照
题目链接:https://www.luogu.org/problemnew/show/P2871

题目描述

有N件物品和一个容量为V的背包。第i件物品的重量是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的重量总和不超过背包容量,且价值总和最大。
输入格式:
第一行:物品个数N和背包大小M
第二行至第N+1行:第i个物品的重量C[i]和价值W[i]
输出格式:
输出一行最大价值。
样例:
输入:
4 6
1 4
2 6
3 12
2 7
输出:
23
分析这是一道标准的动态规划题——01背包。
首先01背包01的意思在物品中,一件物品只有两种状态——选与不选
那么我们可以设一个二维数组 f[m][n];
解释m与n的关系 m指按顺序选到第m件,n指当背包容量为n时的最大值;
通过题意我们设置两个一维数组 c[i]表示第i件物品的重量(所占位置/代价等等),w[i]指选了这件物品后所获得的价值(回报/分数等等)。
那么我们通过一件物品只有被选与不被选两种推一下DP方程:

当这件物品被选时
可知 f[m][n]=f[m-1][n-c[m]]+w[m]
(当然这个物品需要足够的空间 可以看后面代码)
解释:
当选到第m件时必定与这前一件的最大值有关 因为选了这第m件物品 那必定要从n-c[m]推来 那你选了第m件 必定要加上价值即w[m]
当这件物品不被选时
可知 f[m][n]=f[m-1][n]
解释:
同样的 当选到第m件时必定与这件物品的前一件有关 所以从m-1推来 因为不被选 所以不占体积 所以可以不用考虑n
通过上面两情况,又因为我们的定义 f[m][n]应为最大值 那么f[m][n]应为上面两种情况的最大值
即DP方程: f[m][n]=max(f[m-1][n-c[m]+w[m],f[m-1][n])
那么关于这道最后只要输出f[总件数][总体积]不必多说
代码实现:

#include<iostream>
#include<cstdio>
using namespace std;
long long f[10000][10000],c[100000],w[100000],s,v;
int main()
{
cin>>s>>v;
for(long long i=1;i<=s;i++)
cin>>c[i]>>w[i];
for(long long m=1;m<=s;m++)
for(long long n=v;n>0;n--)//为了保证一定能装下这件物品 
{ 
if(n>=c[m]) //如果能装下 
f[m][n]=max(f[m-1][n],f[m-1][n-c[m]]+w[m]);
else//不能装下的话必定不能选
f[m][n]=f[m-1][n]; 
} 
cout<<f[s][v];
return 0;
}


重点:状态压缩:

我们通过上面的解释可以了解到一点——
f[m][n]无论怎么选都必定于f[m-1][n或n-c[m]]的值有关(划重点)
那我们是不是可以将f[m][n]这个数组状态压缩到f[n]一维呢?
答案是可以的
在原本的二维DP中
我们运用双重for来更改数组的数值
那么必定一个数组会被分为两部分 一部分为修改好的f[n](即f[m][n])
另一部分为上个for修改的 而这个for还没修改到的(即f[m-1][n])
那么我们修改f[n]时只要能调动这次for还没修改到的 就可以实现二维DP的压缩
那么我们在原本二维DP思考
修改f[m][n]所调动的f[m-1][n或n-c[m]]容量(即它们各自对应的n)是比f[m][n]小的
那我们可以优先从容量大的修改起
那么就可以保证在修改f[n]时所调动f[n或n-c[m]]是还没修改的
(有些难理解,自己结合题目多思考)
放上一维压缩后的代码

#include<iostream>
#include<cstdio>
using namespace std;
long long f[1000000],c[100000],w[100000],s,v;
int main()
{
cin>>s>>v;
for(long long i=1;i<=s;i++)
cin>>c[i]>>w[i];
for(long long m=1;m<=s;m++)
for(long long n=v;n>0;n--) //重点理解 
{ 
if(n>=c[m]) //如果能装下 
f[n]=max(f[n],f[n-c[m]]+w[m]);
else//不能的话必定不能选
f[n]=f[n]; 
} 
cout<<f[v];
return 0;
}


就解释到这里
第一篇博客 感谢支持

猜你喜欢

转载自www.cnblogs.com/dixiao/p/11235930.html