背包问题
0/1背包问题
题目:
- 给定n种物品和一个容量为c的背包,物品i的重量是 wi,其价值为vi。问︰应该如何选择装入背包的物品,使得装入背包中的物品的总价值最大?
问题分析:
- 面对每个物品,我们只有选择拿或者不拿两种选择,不能选择装入某物品的一部分,也不能装入同一物品多次。
- 0/1背包问题中的0代表这个物品不拿,1代表这个物品拿。是一个拿与不拿的问题。
例题及输入输出:

例题的动态规划(DP)
| w[i] | c[i] | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 
| 2 | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 
| 3 | 3 | 0 | 0 | 1 | 3 | 3 | 4 | 4 | 4 | 4 | 4 | 4 | 
| 4 | 5 | 0 | 0 | 1 | 3 | 5 | 5 | 6 | 8 | 8 | 9 | 9 | 
| 7 | 9 | 0 | 0 | 1 | 3 | 5 | 5 | 6 | 9 | 9 | 10 | 12 | 
例题代码
//0/1背包问题 
#include<stdio.h> 
#include<stdlib.h>
int dp[35][205];
int w[35],c[35];
int max(int a,int b)
{
	if(a>=b){
		return a;
	}
	return b;
}
int main()
{
	int i=0,j=0;
	int m,n;//m代表背包容量,n代表物品数量 
	printf("请输入m和n的值:\n");
	scanf("%d",&m);
	scanf("%d",&n);
	for(i=1;i<=n;i++){//键盘输入物品重量的数组 
		scanf("%d",&w[i]);
	} 
	for(i=1;i<=n;i++){//键盘输入物品价值的数组 
		scanf("%d",&c[i]);
	} 
	//dp表的计算算法部分 
	for(i=1;i<=n;i++){
		for(j=1;j<=m;j++){
			if(j<w[i]){
				dp[i][j]=dp[i-1][j];
			}else{
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-w[i]]+c[i]);
			}
		}
	}
	//输出dp表 
	printf("dp表如下所示:\n");
	for(i=0;i<=n;i++){
		for(j=0;j<=m;j++){
			printf("%-3d",dp[i][j]);
		}
		printf("\n");
	}
	
	printf("背包能放入的最大价值为:%d\n",dp[n][m]);
	return 0;
}
完全背包问题
例题及输入输出:

例题的动态规划(DP)
| w[i] | c[i] | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 
| 2 | 1 | 0 | 0 | 1 | 1 | 2 | 2 | 3 | 3 | 4 | 4 | 5 | 
| 3 | 3 | 0 | 0 | 1 | 3 | 3 | 4 | 6 | 6 | 7 | 9 | 9 | 
| 4 | 5 | 0 | 0 | 1 | 3 | 5 | 5 | 6 | 8 | 10 | 10 | 11 | 
| 7 | 9 | 0 | 0 | 1 | 3 | 5 | 5 | 6 | 9 | 9 | 10 | 12 | 
例题代码
//完全背包问题
//化简前写法 
#include<stdio.h>
#include<stdlib.h>
int w[50],c[50],dp[210]; 
int max(int x,int y)
{
	if(x>y){
		return x;
	}
	return y;
}
int main()
{
	int m,n;
	int i=0,j=0,k=0;
	printf("请输入m和n的值:\n");
	scanf("%d",&m);
	scanf("%d",&n);
	printf("请输入w[i]数组的值:\n");
	for(i=1;i<=n;i++){
		scanf("%d",&w[i]);
	}
	printf("请输入c[i]数组的值:\n");
	for(i=1;i<=n;i++){
		scanf("%d",&c[i]);
	}
	for(i=1;i<=n;i++){
		for(j=m;j>=1;j--){
			for(k=0;k<=j/w[i];k++){
				dp[j]=max(dp[j],dp[j-k*w[i]]+k*c[i]);
			}
		}
	}
	
	printf("%d",dp[m]);
	return 0;
} 
多重背包问题
题目:
- 有N种物品和一个容量为V的背包。第i种物品最多有n[i]件可用,每件费用是c[i],价值是w[i]。求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大。
问题分析:
- 我们仔细观察题目,会发现不同点在于每种物品的数量,01背包是每种只有1件,完全背包是每种无限件,而多重背包是每种有限件。
例题及输入输出:

例题代码
#include<stdio.h>
#include<stdlib.h> 
int max(int x,int y)
{
	if(x>y){
		return x;
	}
	return y;
}
int v[510],w[510],s[510],dp[6100];//v数组代表价格,w数组代表价值,s数组代表数量 
int main()
{
	int n,m;
	int i,j,k;
	printf("请输入n和m的值:\n");
	scanf("%d",&n);
	scanf("%d",&m);
	for(i=1;i<=n;i++){
		scanf("%d",&v[i]);
		scanf("%d",&w[i]);
		scanf("%d",&s[i]);
	}
	
	for(i=1;i<=n;++i){
		for(j=m;j>=1;--j){
			for(k=0;k<=s[i]&&k*v[i]<=j;++k){
				dp[j]=max(dp[j],dp[j-k*v[i]]+k*w[i]);
			}
		}
	}
	
	printf("%d",dp[m]);
	
	return 0;
} 
背包问题系列
原文:https://www.cnblogs.com/rosy1203/p/15114213.html