背包复习(代码片段)

milky-w milky-w     2022-11-13     566

关键词:

01背包

问题描述

已知:有一个容量为 V 的背包和 N 件物品,第 i 件物品的重量是 weight[ i ],收益是 cost[ i ]。

限制:每种物品只有一件,可以选择放或者不放

问题:在不超过背包容量的情况下,最多能获得多少价值或收益

相似问题:在恰好装满背包的情况下,最多能获得多少价值或收益

这里,我们先讨论在不超过背包容量的情况下,最多能获得多少价值或收益。

基本思路

01背包的特点:每种物品只有一件,可以选择放或者不放

状态转移方程:f[ i ][ v ] = max( f[ i - 1 ][ v ] , f[ i - 1 ][ v - weight[ i ] ] + cost[ i ] )

代码

技术分享图片
 1 #include <iostream>  
 2 using namespace std;  
 3   
 4 const int N = 3;//物品个数  
 5 const int V = 5;//背包最大容量  
 6 int weight[N + 1] = 0,3,2,2;//物品重量  
 7 int value[N + 1] = 0,5,10,20;//物品价值  
 8   
 9 int f[N + 1][V + 1] = 0;  
10   
11 int Max(int x,int y)  
12   
13     return x > y ? x : y;  
14   
15   
16 /* 
17 目标:在不超过背包容量的情况下,最多能获得多少价值 
18  
19 子问题状态:f[i][j]:表示前i件物品放入容量为j的背包得到的最大价值 
20  
21 状态转移方程:f[i][j] = maxf[i - 1][j],f[i - 1][j - weight[i]] + value[i] 
22  
23 初始化:f数组全设置为0 
24 */  
25 int Knapsack()  
26   
27     //初始化  
28     memset(f,0,sizeof(f));  
29     //递推  
30     for (int i = 1;i <= N;i++) //枚举物品  
31       
32         for (int j = 0;j <= V;j++) //枚举背包容量  
33           
34             f[i][j] = f[i - 1][j];  
35             if (j >= weight[i])  
36               
37                 f[i][j] = Max(f[i - 1][j],f[i - 1][j - weight[i]] + value[i]);  
38               
39           
40       
41     return f[N][V];  
42   
43   
44 int main()  
45   
46     cout<<Knapsack()<<endl;  
47     return 1;  
48 
二维数组
技术分享图片
 1 #include <iostream>  
 2 using namespace std;  
 3   
 4 const int N = 3;//物品个数  
 5 const int V = 5;//背包最大容量  
 6 int weight[N + 1] = 0,3,2,2;//物品重量  
 7 int value[N + 1] = 0,5,10,20;//物品价值  
 8   
 9 int f[V + 1] = 0;  
10   
11 int Max(int x,int y)  
12   
13     return x > y ? x : y;  
14   
15   
16 /* 
17 目标:在不超过背包容量的情况下,最多能获得多少价值 
18  
19 子问题状态:f[j]:表示前i件物品放入容量为j的背包得到的最大价值 
20  
21 状态转移方程:f[j] = maxf[j],f[j - weight[i]] + value[i] 
22  
23 初始化:f数组全设置为0 
24 */  
25 int Knapsack()  
26   
27     //初始化  
28     memset(f,0,sizeof(f));  
29     //递推  
30     for (int i = 1;i <= N;i++) //枚举物品  
31       
32         for (int j = V;j >= weight[i];j--) //枚举背包容量,防越界,j下限为 weight[i]  
33           
34             f[j] = Max(f[j],f[j - weight[i]] + value[i]);  
35           
36       
37     return f[V];  
38   
39   
40 int main()  
41   
42     cout<<Knapsack()<<endl;   
43     return 1;  
44 
一维数组

 

恰好装满

使用二维数组f[i][v]存储中间状态,其中第一维表示物品,第二维表示背包容量;初始化时,除了f[i][0] = 0(第一列)外,其他全为负无穷。

技术分享图片
 1 #include <iostream>  
 2 using namespace std;  
 3   
 4 const int MinNum = 0x80000000;  
 5   
 6 const int N = 3;//物品个数  
 7 const int V = 5;//背包最大容量  
 8 int weight[N + 1] = 0,3,2,2;//物品重量  
 9 int value[N + 1] = 0,5,10,20;//物品价值  
10   
11 int f[N + 1][V + 1] = 0;  
12   
13 int Max(int x,int y)  
14   
15     return x > y ? x : y;  
16   
17   
18 /* 
19 目标:在恰好装满背包的情况下,最多能获得多少价值 
20  
21 子问题状态:f[i][j]:表示前i件物品放入容量为j的背包得到的最大价值 
22  
23 状态转移方程:f[i][j] = maxf[i - 1][j],f[i - 1][j - weight[i]] + value[i] 
24  
25 初始化:f数组全设置为0 
26 */  
27 int Knapsack()  
28   
29     //初始化  
30     for (int i = 0;i <= N;i++) //枚举物品  
31       
32         for (int j = 0;j <= V;j++) //枚举背包容量  
33           
34             f[i][j] = MinNum;  
35           
36       
37     for (int i = 0;i <= N;i++)  
38       
39         f[i][0] = 0;//背包容量为0时为合法状态  
40       
41     //递推  
42     for (int i = 1;i <= N;i++) //枚举物品  
43       
44         for (int j = 1;j <= V;j++) //枚举背包容量  
45           
46             f[i][j] = f[i - 1][j];  
47             if (j >= weight[i])  
48               
49                 f[i][j] = Max(f[i - 1][j],f[i - 1][j - weight[i]] + value[i]);  
50               
51           
52       
53     return f[N][V];  
54   
55   
56 int main()  
57   
58     cout<<Knapsack()<<endl;//输出25   
59     return 1;  
60 
二维数组
技术分享图片
 1 #include <iostream>  
 2 using namespace std;  
 3   
 4 const int MinNum = 0x80000000;//int最小的数  
 5   
 6 const int N = 3;//物品个数  
 7 const int V = 5;//背包最大容量  
 8 int weight[N + 1] = 0,3,2,2;//物品重量  
 9 int value[N + 1] = 0,5,10,20;//物品价值  
10   
11 int f[V + 1] = 0;  
12   
13 int Max(int x,int y)  
14   
15     return x > y ? x : y;  
16   
17   
18 /* 
19 目标:在恰好装满背包容量的情况下,最多能获得多少价值 
20  
21 子问题状态:f[j]:表示前i件物品放入容量为j的背包得到的最大价值 
22  
23 状态转移方程:f[j] = maxf[j],f[j - weight[i]] + value[i] 
24  
25 初始化:f数组全设置为0 
26 */  
27 int Knapsack()  
28   
29     //初始化  
30     for (int i = 0;i <= V;i++)  
31       
32         f[i] = MinNum;  
33       
34     f[0] = 0;//只有背包容量为0时才是合法状态,由合法状态组成的结果才是合法的  
35   
36     //递推  
37     for (int i = 1;i <= N;i++) //枚举物品  
38       
39         for (int j = V;j >= weight[i];j--) //枚举背包容量,防越界,j下限为 weight[i]  
40           
41             f[j] = Max(f[j],f[j - weight[i]] + value[i]);  
42           
43       
44     return f[V];  
45   
46   
47 int main()  
48   
49     cout<<Knapsack()<<endl;//输出25   
50     return 1;  
51 
一维数组

 

完全背包

问题描述

已知:有一个容量为 V 的背包和 N 件物品,第 i 件物品的重量是 weight[ i ],收益是 cost[ i ]。

条件:每种物品都有无限件,能放多少就放多少。

问题:在不超过背包容量的情况下,最多能获得多少价值或收益。

基本思路

方法有拆分物品、二进制转换等,但都太慢。

只需将逆序枚举的01背包改成顺序枚举即可。

代码

技术分享图片
 1 #include <iostream>  
 2 #include <vector>  
 3 #include <assert.h>  
 4 using namespace std;  
 5 const int N = 3;  
 6 const int V = 5;//5  
 7 int weight[N + 1] = 0,3,2,2;  
 8 int Value[N + 1] = 0,5,10,20;  
 9   
10 int f[N + 1][V + 1] = 0;  
11   
12 int Completeknapsack()  
13   
14     //初始化  
15     for (int i = 0;i <= N;i++)  
16       
17         f[i][0] = 0;  
18       
19     for (int v = 0;v <= V;v++)  
20       
21         f[0][v] = 0;  
22       
23     for (int i = 1;i <= N;i++)  
24       
25         for (int v = weight[i];v <= V;v++)  
26           
27             f[i][v] = max(f[i - 1][v],f[i][v - weight[i]] + Value[i]);  
28           
29       
30     return f[N][V];  
31   
32   
33 int main()  
34   
35     cout<<Completeknapsack()<<endl;   
36     return 1;  
37 
二维数组
技术分享图片
 1 include <iostream>  
 2 using namespace std;  
 3 const int N = 3;  
 4 const int V = 5;//5  
 5 int weight[N + 1] = 0,3,2,2;  
 6 int Value[N + 1] = 0,5,10,20;  
 7   
 8 int f[V + 1] = 0;  
 9   
10 int Completeknapsack()  
11   
12     f[0] = 0;  
13     for (int i = 1;i <= N;i++)  
14       
15         for (int v = weight[i];v <= V;v++)  
16           
17             f[v] = max(f[v],f[v - weight[i]] + Value[i]);  
18           
19       
20     return f[V];  
21   
22 int main()  
23   
24     cout<<Completeknapsack()<<endl;  
25     return 1;  
26 
一维数组

 


from 远航之曲

 

01背包问题复习(代码片段)

01背包问题复习518.零钱兑换IIeasyclassSolution//amount=5,coins=[1,2,5]问有多少种方法用coins凑成amountpublicintchange(intamount,int[]coins)int[]dp=newint[amount+1];dp[0]=1;for(intval:coins)for(inti= 查看详情

背包复习(代码片段)

01背包问题描述已知:有一个容量为V的背包和N件物品,第i件物品的重量是weight[i],收益是cost[i]。限制:每种物品只有一件,可以选择放或者不放问题:在不超过背包容量的情况下,最多能获得多少价值或收益相似问题:在恰好... 查看详情

dp复习01背包ovo(代码片段)

水题10s切得pj-的那种QAQ P1048采药1#include<cstdio>2#include<iostream>3usingnamespacestd;4constintsz=1010;5intdp[sz],val[sz],tim[sz];6intt,m;7intmain()8scanf("%d%d",&t,&m);9for(inti=1; 查看详情

01背包问题复习(代码片段)

01背包问题复习518.零钱兑换IIeasyclassSolution//amount=5,coins=[1,2,5]问有多少种方法用coins凑成amountpublicintchange(intamount,int[]coins)int[]dp=newint[amount+1];dp[0]=1;for(intval:coins)for(inti=val;i<=amount;i++)//如果是背包里的物... 查看详情

01背包与完全背包(dp复习)(代码片段)

01背包和完全背包都是dp入门的经典,我的dp学的十分的水,借此更新博客的机会回顾一下01背包:给定总容量为maxv的背包,有n件物品,第i件物品的的体积为w[i],价值为v[i],问如何选取才能是背包内的物品价值总和最大。stdin:5123... 查看详情

复习动规(代码片段)

...规划。 单调队列优化dp第一道,宝物筛选。一道多重背包优化题。如果用二进制优化很好做,但时间复杂度是O(nW*logm)。单调队列优化做法如下:首先做出普通的多重背包的转移方程:f[j]=maxf[j-w*k]+v*k,w为重量,v为价值。使... 查看详情

iloveexamhdu-6968(代码片段)

...数目不能超过p,问所有达到的最大分数题解:01背包有两个背包转移过程首先不用考虑挂科的事,我们将试题按照名称排序 查看详情

算法复习——背包dp

1.01背包  二维递推式子:   代码:  for(i=1;i<=n;i++)for(x=m;x>=1;x--)if(x>=w[i])f[i][x]=max(f[i-1][x-w[i]]+c[i],f[i-1][x]);elsef[i][x]=f[i-1][x];printf("%d",f[n][m]);// 查看详情

codevs3269混合背包(复习混合背包)

传送门【题目大意】给出物品的数量。-1为无限个。【思路】混合背包....【code】#include<iostream>#include<cstdio>#include<cstdlib>usingnamespacestd;intw[100000],v[100000],c[10000],dp[20000000];intmain(){intvv,n;scanf("% 查看详情

背包问题(代码片段)

复健\\(Day1\\)今天复习基础背包问题,在\\(ACWing\\)上使用挑战模式去打模板,提高打代码速度\\(01\\)背包解决每种物品只有一样的情况时间复杂度\\(O(nV)\\),空间复杂度优化后为\\(O(V))\\)空间优化的代码中体积一维从后往前更新,... 查看详情

悼念512汶川大地震遇难同胞——珍惜现在,感恩生活(复习多重背包)

...量,价格,袋数。求购买大米的最终重量。【思路】多重背包。【复习】多重背包特点。题目 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品... 查看详情

背包问题(代码片段)

目录背包问题来源动态规划的关键点No.1:01背包问题分析codeNo.2:完全背包问题分析方法一code方法二codeNo.3:多重背包(未完待续)背包问题来源完全基于中山纪念中学宋新波ppt的一次复习动态规划的关键点最优化原理子问题最优... 查看详情

piggy-bank(复习完全背包)

...和重量。求装满储钱罐时最小能得到多少钱。题解:完全背包变形。因为要求最小一开始赋值大数。code: #include<iostream>#include<cstdio>#include<cstring>usingnamespacestd;intw1,w2,wi,t,k,f 查看详情

算法设计与分析期中考试复习:代码和经典题目分治二分动态规划(未完待续)(代码片段)

...:矩阵相乘,数塔,最长公共子序列,0-1背包。快速排序思想: 查看详情

dp复习 背包[礼物]

【问题描述】人生赢家老王在网上认识了一个妹纸,然后妹纸的生日到了,为了表示自己的心意,他决定送她礼物。可是她喜爱的东西特别多,然而他的钱数有限,因此他想知道当他花一定钱数后剩余钱数无法再购买任何一件剩... 查看详情

背包0-1背包与完全背包一维数组实现(代码片段)

背包问题很经典了,《背包问题九讲》讲的非常详细,建议看一看。在这里,我想给出0-1背包和完全背包压缩空间后的实现,即只要一维数组。0-1背包,与完全背包仅仅只是内循环的次序不同,故而代码基本相同。希望可以帮的... 查看详情

背包问题(代码片段)

背包问题分类:0-1背包(每种物品只有一个)完全背包(每种物品无限多)多重背包(每种物品Mi个,0-1背包算是多重背包的特殊情况)混合背包。。。解决此类问题主要将其转化为0-1背包的问题&#x... 查看详情

动态规划_01背包_完全背包_多重背包_分组背包(代码片段)

目录动态规划问题结题思路:模板题链接:01背包思路:代码:完全背包思路:代码多重背包思路:代码:组合背包思路:代码:动态规划问题结题思路:模板题链接:01背包模板题完全背包... 查看详情