0-1背包问题与完全背包问题C++实现 动态规划

今天看了看背包九讲,自己写了下0-1背包和完全背包

王晓东《计算机算法分析与设计》上面给出的C++实现比较繁琐,相比而言这个版本更加简明

给出了测试数据

0-1背包问题C++实现

/*任务:计算0-1背包问题的最大价值
Sample Input
10 4
2 1
3 3
4 5
7 9
Sample Output
12
0 1 0 1
*/
#include<stdio.h>
#include<string.h>
int c[20][1000];//c[k][y]为只允许装前k种物品,背包总重量不超过y的最大价值
int inumber[21][1000];//inumber[k][u]为只允许装前K种物品,背包总重量不超过y时得到最大价值时使用的背包的最大标号
int w[21],p[21];
int knapsack(int m,int n)
{
	int i,j;
    for(i=1;i<n+1;i++)
        scanf("%d%d",&w[i],&p[i]);
    memset(c,0,sizeof(c));
	memset(inumber,0,sizeof(inumber));
	for(j=1;j<m+1;j++){
		c[1][j]=j/w[1]*p[1];
	}
    for(i=1;i<n+1;i++){
		for(j=1;j<m+1;j++){
			if(j >= w[i]){
				if(p[i]+c[i-1][j-w[i]]>=c[i-1][j]){
					c[i][j]=p[i]+c[i-1][j-w[i]];
					inumber[i][j]=i;
				}	
                else{
					c[i][j]=c[i-1][j];
					inumber[i][j]=inumber[i-1][j]; 
				}
			}
			else{
				c[i][j]=c[i-1][j];
				inumber[i][j]=inumber[i-1][j]; 
			}
		}
	}
	return(c[n][m]);                     
}

void trackSolution(int m, int n){
	int x[21];
	int y = m;
	int j = n;
	memset(x, 0, sizeof(x));
	while(true){
		j = inumber[j][y];
		x[j] = 1;
		y = y - w[j];
		while(inumber[j][y] == j){
			y = y - w[j];
			x[j]++;
		}
		if(!inumber[j][y]) break;
	}
	printf("最大价值方案中各个物品的个数为(物品标号从1到n):");
	for(j = 1; j <= n; j++){
		printf("%d ", x[j]);
	}
	printf("\n");
}
int main()
{
	int m,n;
	while(scanf("%d%d",&m,&n)!=EOF){
		printf("最大价值为%d\n",knapsack(m,n));
		trackSolution(m, n);
	}
	return 0;
}

完全背包问题C++实现

/*任务:计算完全背包问题的最大价值
Sample Input
10 4
2 1
3 3
4 5
1 9
Sample Output
90
0 0 0 10
*/
#include<stdio.h>
#include<string.h>
int c[20][1000];//c[k][y]为只允许装前k种物品,背包总重量不超过y的最大价值
int inumber[21][1000];//inumber[k][u]为只允许装前K种物品,h背包总重量不超过y时得到最大价值时使用的背包的最大标号
int w[21],p[21];
int knapsack(int m,int n)
{
	int i,j;
    for(i=1;i<n+1;i++)
        scanf("%d%d",&w[i],&p[i]);
    memset(c,0,sizeof(c));
	memset(inumber,0,sizeof(inumber));
	for(j=1;j<m+1;j++){
		c[1][j]=j/w[1]*p[1];
	}
    for(i=1;i<n+1;i++){
		for(j=1;j<m+1;j++){
			if(j >= w[i]){
				if(p[i]+c[i][j-w[i]]>=c[i-1][j]){//和0-1背包相比只是将c[i-1][j-w[i]]写成了c[i][j-w[i]],因为完全背包问题中每件物品有无限个
					c[i][j]=p[i]+c[i][j-w[i]];
					inumber[i][j]=i;
				}	
                else{
					c[i][j]=c[i-1][j];
					inumber[i][j]=inumber[i-1][j]; 
				}
			}
			else{
				c[i][j]=c[i-1][j];
				inumber[i][j]=inumber[i-1][j]; 
			}
		}
	}
	return(c[n][m]);                     
}

void trackSolution(int m, int n){
	int x[21];
	int y = m;
	int j = n;
	memset(x, 0, sizeof(x));
	while(true){
		j = inumber[j][y];
		x[j] = 1;
		y = y - w[j];
		while(inumber[j][y] == j){
			y = y - w[j];
			x[j]++;
		}
		if(!inumber[j][y]) break;
	}
	printf("最大价值方案中各个物品的个数为(物品标号从1到n):");
	for(j = 1; j <= n; j++){
		printf("%d ", x[j]);
	}
	printf("\n");
}
int main()
{
	int m,n;
	while(scanf("%d%d",&m,&n)!=EOF){
		printf("最大价值为%d\n",knapsack(m,n));
		trackSolution(m, n);
	}
	return 0;
}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值