其他分享
首页 > 其他分享> > 令人头疼的背包九讲(2)完全背包问题

令人头疼的背包九讲(2)完全背包问题

作者:互联网

重磅干货,第一时间送达
令人头疼的背包九讲(2)完全背包问题

背包问题是一个经典的动态规划模型。它既简单形象容易理解,又在某种程度上能够揭示动态规划的本质,故不少教材都把它作为动态规划部分的第一道例题.

题目

完全背包问题

题目要求

有n个重量和价值分别为wi,vi的物品,从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中价值总和的最大值
1≤n≤100
1≤wi,vi≤100
1≤W≤10000

输入:
整数用空格隔开

第一行有两个整数N,V 代表物品种数和背包容积

接下来有N行,每行两个整数用空格隔开,代表物品体积和价值

输出:
在背包容量下能够最大化的价值

输入样例

4 6
1 1
2 3
3 4
4 5

输出样例:

9

分析

与零一背包不同的是,零一背包中的物品是不可以重复拿取的,只可以拿取当前物品或者不拿取当前物品,不可以拿取多个,完全背包的物品是可以任意拿取多个的来构成不超过背包容量并且构成的总价值是最大的

动态规划的核心是找到dp公式或者状态转移的方程,理解清楚中间的过程是怎么样进行变化的,因为动态规划总是要利用到之前历史上的最佳方案,所以dp数组里面存储的肯定是历史上存储的最佳方案,一开始的时候我们是可以借助excel表格来帮助我们理解dp数组是怎样生成的

我们可以这样想:当前我的背包容量有多少,而且我可以选择的物品的范围是什么,那么这两个变量就可以确定一个值了,我们可以计算出当前背包容量对于当前可以选择的物品范围构成的最大价值

解题步骤

表格说明


表格

令人头疼的背包九讲(2)完全背包问题
由输入可知第一个物品为1 1 即价值为1,所占的容量也为1。

根据f[i][j]=max(f[i][j-w[i]]+v[i])可知,从第一个物品开始,由于今天这个问题属于完全背包问题,故两层循环中,第一层循环为遍历物品,第二层循环为从小到大扩大背包容量不断塞进更多的当前物品。

f[1][0]=max(f[1][0],f[1][0-1]+2) 不执行
执行 f[1][0]=f[0][0]
从上式可以知道我我们取不到f[1][0-1] 故加个判断j>=w[i]即可,若满足就可以加入物品,不满足就不更新仍维持0

f[1][1]=max(f[1][1],f[1][1-1]+2)
f[1][2]=max(f[1][2],f[1][2-1]+2)
f[1][3]=max(f[1][3],f[1][3-1]+2)
f[1][4]=max(f[1][4],f[1][4-1]+2)
f[1][5]=max(f[1][5],f[1][5-1]+2)

这样第一个物品结束后,我们来看看整个二维数组的更新情况

令人头疼的背包九讲(2)完全背包问题
f[1][5]就表示了在选择第一个物品的时候,容量为5的情况下的最大价值为5


接下来更新第二个物品

加个判断j-w[i]>=0,若满足就可以加入物品,不满足就不更新仍维持0

f[2][0]=max(f[2][0],f[2][0-2]+3) 不执行
故执行f[2][0]=f[1][0]
f[2][1]=max(f[2][1],f[2][1-2]+3) 不执行
故执行f[2][1]=f[1][1]

f[2][2]=max(f[2][2],f[2][2-2]+3)
f[2][3]=max(f[2][3],f[2][3-2]+3)
f[2][4]=max(f[2][4],f[2][4-2]+3)
f[2][5]=max(f[2][5],f[2][5-2]+3)

这样第二个物品结束后,我们来看看整个二维数组的更新情况

令人头疼的背包九讲(2)完全背包问题

以此类推最后得到整个二维数组的情况为

令人头疼的背包九讲(2)完全背包问题

代码

Python :

 1a=input()
 2n, m=list(map(int, a.split()))
 3w=[0 for i in range(n + 1)]
 4v=[0 for i in range(n + 1)]
 5f=[0 for i in range(m + 1)]
 6for i in range(1, n + 1):
 7    b=input()
 8    w[i], v[i]=list(map(int, b.split()))
 9
10for i in range(1, n + 1):
11    for j in range(1, m + 1):
12        if j >= w[i]:
13            f[j]=max(f[j], f[j - w[i]] + v[i])
14            # 这个是考虑到可以选取多个物品的情况
15
16print(f[-1])

C++

 1int main(){
 2    int N,V;
 3    cin>>N>>V;
 4    vector<int> weight(N+1),value(N+1);
 5    for(int i=1;i<=N;i++)
 6        cin>>weight[i]>>value[i];
 7    vector<vector<int>> dp(N+1,vector<int>(V+1,0)); 
 8    for(int i=1;i<weight.size();i++){
 9        for(int j=0;j<=V;j++){
10
11            dp[i][j]=dp[i-1][j];
12
13            if(j-weight[i]>=0) 
14                dp[i][j]=max(dp[i-1][j],dp[i][j-weight[i]]+value[i]);
15        }
16    }
17    cout<<dp[N][V]<<endl;
18}
19

后记

2020大厂笔试 | 网易提前批(1)

2020大厂笔试 | 网易提前批(2)

令人头疼的背包九讲(1)0/1背包

数据结构类题目

剑指offer刷题交流群

扫码添加微信,一定要备注研究方向+地点+学校+昵称(如机器学习+上海+上交+汤姆),只有备注正确才可以加群噢。

令人头疼的背包九讲(2)完全背包问题
▲长按加群

令人头疼的背包九讲(2)完全背包问题

标签:头疼,背包,九讲,max,链表,二叉树,数组,物品
来源: https://blog.51cto.com/15054042/2564536