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、普通解法
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 //可以边读入边动态规划么
2、边读入边dp
因为f[i][j]表示前i件物品花费j元的最大价值
算到f[i][j]的时候只需要用到前i种物品
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 //可以边读入"边动态规划么
3、单维数组优化
一维数组的情况下,j必须从后往前,不然会导致同一件物品被选多次,而每件物品只有一样
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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背包的分组背包的一维数组优化
4、分组背包
普通解法相当于把k省略了,因为每件物品就一件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 //可以边读入边动态规划么
5、分组背包单数组优化
j还是得从后往前,因为j的顺序只和f数组的维数相关,而和这里的k没有关系
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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背包的分组背包的一维数组优化