//f[i][j]表示前i件物品花费j元的最大价值
//f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i])
//f[i][0]=0 f[0][j]=0
1、普通解法
1 //f[i][j]表示前i件物品花费j元的最大价值
2 //f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i])
3 //f[i][0]=0 f[0][j]=0
4
5 #include <bits/stdc++.h>
6 using namespace std;
7 int f[105][105];
8 int m,n;
9 int w[105],c[105];
10
11 int main(){
12 freopen("in1.txt","r",stdin);
13 cin>>m>>n;
14 for(int i=1;i<=n;i++){
15 cin>>w[i]>>c[i];
16 }
17 //初始化dp
18 int tmp=max(m,n);
19 for(int i=0;i<=tmp;i++){
20 f[i][0]=0;
21 f[0][i]=0;
22 }
23
24 for(int i=1;i<=n;i++){
25 for(int j=1;j<=m;j++){
26 f[i][j]=f[i-1][j];
27 if(j>=w[i]){
28 f[i][j]=max(f[i][j],f[i-1][j-w[i]]+c[i]);
29 }
30 }
31 }
32 cout<<f[n][m]<<endl;
33
34 return 0;
35 }
36
37
38 //单数组
39 //可以边读入边动态规划么
01背包
2、边读入边dp
因为f[i][j]表示前i件物品花费j元的最大价值
算到f[i][j]的时候只需要用到前i种物品
1 //f[i][j]表示前i件物品花费j元的最大价值
2 //f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i])
3 //f[i][0]=0 f[0][j]=0
4
5 #include <bits/stdc++.h>
6 using namespace std;
7 int f[105][105];
8 int m,n;
9 int w[105],c[105];
10
11 int main(){
12 freopen("in1.txt","r",stdin);
13 //初始化dp
14 memset(f,0,sizeof(f));
15
16 cin>>m>>n;
17 for(int i=1;i<=n;i++){
18 cin>>w[i]>>c[i];
19 for(int j=1;j<=m;j++){
20 f[i][j]=f[i-1][j];
21 if(j>=w[i]){
22 f[i][j]=max(f[i][j],f[i-1][j-w[i]]+c[i]);
23 }
24 }
25 }
26 cout<<f[n][m]<<endl;
27
28 return 0;
29 }
30
31
32 //单数组
33 //可以边读入"边动态规划么
01背包(边读入边DP)
3、单维数组优化
一维数组的情况下,j必须从后往前,不然会导致同一件物品被选多次,而每件物品只有一样
1 //f[j]表示前i件物品花费j元的最大价值
2 //f[j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i])
3 //f[j]=0
4
5 #include <bits/stdc++.h>
6 using namespace std;
7 int f[105];
8 int m,n;
9 int w[105],c[105];
10
11 int main(){
12 freopen("in1.txt","r",stdin);
13 //初始化dp
14 memset(f,0,sizeof(f));
15 cin>>m>>n;
16 for(int i=1;i<=n;i++){
17 cin>>w[i]>>c[i];
18 }
19
20 //一维数组的情况下,j必须从后往前,不然会导致同一件物品被选多次,没每件物品只有一样
21 for(int i=1;i<=n;i++){
22 for(int j=m;j>=1;j--){
23 if(j>=w[i]){
24 f[j]=max(f[j],f[j-w[i]]+c[i]);
25 }
26 }
27 }
28 cout<<f[m]<<endl;
29
30 return 0;
31 }
32
33
34 //单数组
35 //可以边读入边动态规划么
36 //01背包的分组背包
37 //01背包的分组背包的一维数组优化
01背包(单数组优化)
4、分组背包
普通解法相当于把k省略了,因为每件物品就一件
1 //f[i][j]表示前i件物品花费j元的最大价值
2 //f[i][j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i])
3 //f[i][0]=0 f[0][j]=0
4
5 #include <bits/stdc++.h>
6 using namespace std;
7 int f[105][105];
8 int m,n;
9 int w[105],c[105];
10 int num[105];//代表每样物品的个数
11
12 int main(){
13 freopen("in1.txt","r",stdin);
14 cin>>m>>n;
15 for(int i=1;i<=n;i++){
16 cin>>w[i]>>c[i];
17 num[i]=1;
18 }
19 //初始化dp
20 int tmp=max(m,n);
21 for(int i=0;i<=tmp;i++){
22 f[i][0]=0;
23 f[0][i]=0;
24 }
25
26 //每个物品看做一组,每组只有一个
27 for(int i=1;i<=n;i++){
28 for(int j=1;j<=m;j++){
29 f[i][j]=f[i-1][j];
30 for(int k=1;k<=num[i];k++){
31 if(j>=w[i]){
32 f[i][j]=max(f[i][j],f[i-1][j-w[i]]+c[i]);
33 }
34 }
35 }
36 }
37 cout<<f[n][m]<<endl;
38
39 return 0;
40 }
41
42
43 //单数组
44 //可以边读入边动态规划么
01背包(分组背包)
5、分组背包单数组优化
j还是得从后往前,因为j的顺序只和f数组的维数相关,而和这里的k没有关系
1 //f[j]表示前i件物品花费j元的最大价值
2 //f[j]=max(f[i-1][j],f[i-1][j-w[i]]+c[i])
3 //f[j]=0
4
5 #include <bits/stdc++.h>
6 using namespace std;
7 int f[105];
8 int m,n;
9 int w[105],c[105];
10 int num[105];
11
12 int main(){
13 freopen("in2.txt","r",stdin);
14 //初始化dp
15 memset(f,0,sizeof(f));
16 cin>>m>>n;
17 for(int i=1;i<=n;i++){
18 cin>>w[i]>>c[i];
19 num[i]=1;
20 }
21
22 //一维数组的情况下,j必须从后往前,不然会导致同一件物品被选多次,而每件物品只有一样
23
24 //我们一般01背包只是把k省略了而已,因为k等于1,
25 //所以加上了k后,我们还是需要将j由后向前枚举
26
27 for(int i=1;i<=n;i++){
28 for(int j=m;j>=1;j--){
29 for(int k=1;k<=num[i];k++){
30 if(j>=w[i]){
31 f[j]=max(f[j],f[j-w[i]]+c[i]);
32 }
33 }
34 }
35 }
36 cout<<f[m]<<endl;
37
38 return 0;
39 }
40
41
42 //单数组
43 //可以边读入边动态规划么
44 //01背包的分组背包
45 //01背包的分组背包的一维数组优化
01背包(分组背包单数组优化)
我的旨在学过的东西不再忘记(主要使用艾宾浩斯遗忘曲线算法及其它智能学习复习算法)的偏公益性质的完全免费的编程视频学习网站: fanrenyi.com;有各种前端、后端、算法、大数据、人工智能等课程。