01背包

01背包

//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背包(分组背包单数组优化)
原文地址:https://www.cnblogs.com/Renyi-Fan/p/7499284.html