小数背包问题:简单贪心

问题描述

给定𝑛种物品和一个背包。物品𝑖的重量是𝑊𝑖,其价值为𝑉𝑖,背包的容量为C,应如何 选择装入背包的物品使得装入背包中物品的总价值最大? 这里,在选择物品𝑖装入背包时,可以选择物品𝑖的一部分,而不一定要全部装入背包。

输入

多组测试数据。每组测试包括三行:第一行输入物品的总数𝑛(𝑛 < 1000)和背包的容量 𝐶(𝐶 < 1000)。第二行输入𝑛个整数,表示物品的重量。第三行输入物品的价值。

输出

输出装入背包的总价值,每组测试数据输出一行。

Input

3 50
10 20 30
60 100 120

Output

240

思路

题目要求可以选某个物品的一部分装入背包,则我们可以将背包全部装满,而和01背包不一样的地方就是这里。
分析题目给出样例:
思路1.对价值最大的物品贪心,则是选择第2和第3件物品装入背包,总重量为50,总价值为220;
思路2.对体重最小的物品贪心,则是选择第1件和第2件物品和第三件物品的三分之二((50-10-20)/30)装入背包,总重量为50,总价值为240;
思路3.对价值率(价值除以重量)最大贪心,排序后就是1,2,3,然后对其进行贪心,选择第1件和第2件物品和第三件物品的三分之二((50-10-20)/30)装入背包,总重量为50,总价值为240;
这个样例很巧思路2和思路3得出的结果是一样的,
那么在来看一看下面这个数据。
3 20
18 15 10
25 24 15

(x1,x2,x3)总容量总价值
思路1(1, 2/15, 0)2028.2
思路2(0, 2/3, 1)2031
思路3(0, 1, 1/2)2031.5

所以我们采取第三种思路来做这个题,解题步骤如下:
1.对价值率进行降序;
2.依次选取物品,直到背包容量已满。
下面附上两个代码,第一个是对数据量小的,第二个对数据量较大的。

代码一
#include<stdio.h>
#define MaxSize 1000
typedef struct Node{
	int wight,value;
	double valueRate;
}node;
void InsertSort(int n,node *arr){
	for(int i=1;i<n;i++){
		node temp=arr[i];
		int j=i;
		while(j>0 &&temp.valueRate>arr[j-1].valueRate){
			arr[j]=arr[j-1];//小数往后移 
			j--;
		}
		arr[j]=temp;
	}
}
void SelectionSort(int n,node *arr){
	for(int i=0;i<n-1;i++){
		int mx=i;
		for(int j=i+1;j<n;j++)	
			if(arr[mx].valueRate<arr[j].valueRate)
				mx=j;
		node temp=arr[mx];
		arr[mx]=arr[i];
		arr[i]=temp;
	}
}
double solve(int n,int C,node *arr){
	InsertSort(n,arr);//利用插入排序,对价值率从高到低排序,实行贪心
	//SelectionSort(n,arr);//利用选择排序,对价值率从高到低排序,实行贪心
	double ans=0;
	for(int i=0;i<n;i++){
		if(C>=arr[i].wight){//对价值率贪心,把能去满的物品直接取完 
			ans+=arr[i].value;//背包价值增加这个物品的价值 
			C-=arr[i].wight;//背包容量减少这个物品的重量 
		}
		else{//不能去完的物品,说明背包是最后容纳的某个物品的一部分 
			ans+=(double)C/arr[i].wight*arr[i].value;
			break;
		}
	}
	return ans;
}
int main(){
	int n,C;
	puts("输入物品个数n和背包容量C");
	scanf("%d%d",&n,&C);
	node arr[n];
	printf("输入%d个物品的重量\n",n);
	for(int i=0;i<n;i++)	scanf("%d",&arr[i].wight);
	printf("输入%d个物品的价值\n",n);
	for(int i=0;i<n;i++){
		scanf("%d",&arr[i].value);
		arr[i].valueRate=(double)arr[i].value/arr[i].wight;//算出价值率 
	} 
	double ans=solve(n,C,arr);
	printf("最终背包所装的最大价值为:%.1f",ans);
	return 0;
} 
/*
3 20
18 15 10
25 24 15

3 50
10 20 30
60 100 120
*/
方法二:
#include<stdio.h>
#include<algorithm>
#define MaxSize 1000
using namespace std;
typedef struct Node{
	int wight,value;
	double valueRate;
}node;
bool cmp(node a,node b){//自定义比较函数 
	return a.valueRate>b.valueRate;
}
double solve(int n,int C,node *arr){
	double ans=0;
	for(int i=0;i<n;i++){
		if(C>=arr[i].wight){//对价值率贪心,把能去满的物品直接取完 
			ans+=arr[i].value;//背包价值增加这个物品的价值 
			C-=arr[i].wight;//背包容量减少这个物品的重量 
		}
		else{//不能去完的物品,说明背包是最后容纳的某个物品的一部分 
			ans+=(double)C/arr[i].wight*arr[i].value;
			break;
		}
	}
	return ans;
}
int main(){
	int n,C;
	puts("输入物品个数n和背包容量C");
	scanf("%d%d",&n,&C);
	node arr[n];
	printf("输入%d个物品的重量\n",n);
	for(int i=0;i<n;i++)	scanf("%d",&arr[i].wight);
	printf("输入%d个物品的价值\n",n);
	for(int i=0;i<n;i++){
		scanf("%d",&arr[i].value);
		arr[i].valueRate=(double)arr[i].value/arr[i].wight;//算出价值率 
	}
	sort(arr,arr+n,cmp);//对价值率从高到低排序,实行贪心 
	double ans=solve(n,C,arr);
	printf("最终背包所装的最大价值为:%.1f",ans);
	return 0;
} 
/*
3 20
18 15 10
25 24 15


3 50
10 20 30
60 100 120
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空皓月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值