贪心法求解部分背包问题

背包问题:给定一个载重为M的背包,及n个质量为Wi、价值为Pi的物体,1<=i<=n,要求把物体装满背包,且使得背包内的物体价值最大。

假设:Xi是物体i被装入背包的部分,0<=Xi<=1。当Xi=0时,表示物体i没有被装入背包;当Xi=1时,表示物体i被全部装入背包;当Xi处于0~1之间,表示物体i的一部分被装入背包。根据问题的要求,可以列出下列的约束方程和目标函数:

												![在这里插入图片描述](https://img-blog.csdnimg.cn/20201124220348273.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L1ZhbGVuZGlh,size_16,color_FFFFFF,t_70#pic_center)

于是,问题归结为寻找一个满足约束方程并使目标函数达到最大的解向量X=(X1,X2,X3…Xn)
为使目标函数的值增加最快,一种方法是优先选择价值最大的物体装入背包,这样当最后一个物体装不下时,选择一个适当的Xi<1的物体装入,把背包装满。但是,使用这种方法,不一定能够达到最准的目的。如果所选择的物体重量很大,使得背包载重量的消耗速度太快,以致后续能够装入背包的物体迅速减少,从而便得继续装入背包的物体在满足了约束力程的要求以后,无法达到目标函数的要求。因此,最好是选择既使目标函数的值增加最快,又使背包载重量的消耗较慢的物体装入背包。达到这个目的的一种方法是优先选择价值重量比最大的物体装入背包。基于上述考虑,定义下面的数据结构:

typedef struct{
	float p;//物体的价值
	float w;//物体的质量
	float v;//物体的价值质量比
}WP;
WP instance[MAX];
float x[MAX];

/*
贪婪发求解背包问题
输入:背包载重M,存放物品的价值p、质量m信息的数组instance[  ],物体的数量n
输出:n个物体被装入背包的分量x[i],背包中物体的总价值p
*/
float knapsack_greedy(float M,WP instance[],float x[],int n){
	int i=0;
	float m,p=0;
	for(i=0;i<n;i++){
		instance[i].v=instance[i].p/instance[i].w; //计算每个物品的价值质量比
		x[i]=0;
	}
	mysort(instance,n);
	m=M;
	for(i=0;i<n;i++){ //依次装入价质比高的物品,直到某一刻超过背包可以载重的范围
		if(instance[i].w<=m){
			x[i]=1;
			printf("价质比为%f的物体被取走%f\n",instance[i].v,x[i]);
			m=m-instance[i].w; //背包此时可以载重的重量减少
			p=p+instance[i].p; //背包此时的最大价值增加
		}
		else{ 
			x[i]=m/instance[i].w;//分割物品,物体的部分被装入背包
			printf("价质比为%f的物体被取走%f\n",instance[i].v,x[i]);
			p=p+x[i]*instance[i].p;
			break;
		}
	}
	return p;
}

完整程序代码:

#include<stdio.h>
#define MAX 100
typedef struct{
	float p;//物体的价值
	float w;//物体的质量
	float v;//物体的价值质量比
}WP;
WP instance[MAX];
float x[MAX];

void mysort(WP instance[],int n){
	int i=0,j=0;

	for(i=0;i<n-1;i++)
		for(int j=i+1;j<n;j++)
			if(instance[i].v<instance[j].v){
				WP temp=instance[i];
				instance[i]=instance[j];
				instance[j]=temp;
			}
	printf("输出排序后的物品的\n");
	printf("价值\t\t");printf("质量\t\t");printf("价质比\n");
	for(i=0;i<n;i++)
		printf("%f\t%f\t%f\n",instance[i].p,instance[i].w,instance[i].v);
	printf("\n");
}

/*
贪婪发求解背包问题
输入:背包载重M,存放物品的价值p、质量m信息的数组instance[  ],物体的数量n
输出:n个物体被装入背包的分量x[i],背包中物体的总价值p
*/
float knapsack_greedy(float M,WP instance[],float x[],int n){
	int i=0;
	float m,p=0;
	for(i=0;i<n;i++){
		instance[i].v=instance[i].p/instance[i].w; //计算每个物品的价值质量比
		x[i]=0;
	}
	mysort(instance,n);
	m=M;
	for(i=0;i<n;i++){ //依次装入价质比高的物品,直到某一刻超过背包可以载重的范围
		if(instance[i].w<=m){
			x[i]=1;
			printf("价质比为%f的物体被取走%f\n",instance[i].v,x[i]);
			m=m-instance[i].w; //背包此时可以载重的重量减少
			p=p+instance[i].p; //背包此时的最大价值增加
		}
		else{ 
			x[i]=m/instance[i].w;//分割物品,物体的部分被装入背包
			printf("价质比为%f的物体被取走%f\n",instance[i].v,x[i]);
			p=p+x[i]*instance[i].p;
			break;
		}
	}
	return p;
}

int main(void){
	WP Obj[MAX]={0};
	float p=0;
	int i=0;
	int nwp=MAX; //物品的最大数量
	float c=MAX; //背包可以承载的最大质量

	printf("请输入背包可以承载的重量:");
	scanf("%f",&c);
	printf("请输入物品的总数量:");
	scanf("%d",&nwp);
	printf("\n");
	printf("请输入物体的:\n"); //只是为了看得方便
	printf("价值\t");printf("质量\n");

	for(i=0;i<nwp;i++)	//输入每个物品的价值和质量
		scanf("%f%f",&Obj[i].p,&Obj[i].w);

	p=knapsack_greedy(c,Obj,x,nwp);
	printf("该背包的最大价值是%f\n",p);

	return 0;
}

运行结果:
在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值