贪心算法之阿里巴巴与四十大盗(背包问题)

1、问题

有一天,阿里巴巴赶着一头毛驴上山砍柴。砍好柴准备下山时,远处突然出现一股烟尘,弥漫着直向上空飞扬,朝他这儿卷过来,而且越来越近。靠近以后,他才看清原来是一支马队,他们共有四十人,一个个年轻力壮、行动敏捷。一个首领模样的人背负沉重的鞍袋,从丛林中一直来到那个大石头跟前,喃喃地说道:“芝麻,开门吧!”随着那个头目的喊声,大石头前突然出现一道宽阔的门路,于是强盗们鱼贯而入。阿里巴巴待在树上观察他们,直到他们走得无影无踪之后,才从树上下来。他大声喊道:他小心翼翼地走了进去,一下子惊呆了,洞中堆满了财物,还有多得无法计数的金银珠宝,有的散堆在地区上,有的盛在皮袋中。突然看见这么多的金银财富,“芝麻,开门吧!”他的喊声刚落,洞门立刻打开了。阿里巴巴深信这肯定是一个强盗们数代经营、掠夺所积累起来的宝窟。为了让乡亲们开开眼界,见识一下这些宝物,他想一种宝物只拿一个,如果太重就用锤子凿开,但毛驴的运载能力是有限的,怎么才能用驴子运走最大价值的财宝分给穷人呢?阿里巴巴与四十大盗阿里巴巴陷入沉思中……

2、分析

这里的宝物价值都不一样,然后每个宝物的可以分割的,我们依然可以用贪心算法的思想,我们先找到贪心策略

贪心策略:找到宝物的性价比,然后每次取最大的性价比的宝物放到毛驴身上,然后最后一次如果放不下了就把

剩余的重量放性价比小的分割后的宝物

3、代码实现

普通实现:

#include <iostream>
#include <algorithm>

using namespace std;

//定义数组的个数
const int M = 1000;
//宝物的结构体
struct treasure
{
	//重量
	double weight;
	//价格
	double price;
	//性价比
	double performance;
}data[M];

bool compare(struct treasure t1, struct treasure t2)
{
	return t1.performance > t2.performance;
}

int main()
{
	//毛驴的承重能力和宝物的数量
	int allWeight = 0, allCount = 0;
	std::cout << "请输入毛驴的承重能力和宝物的数量" << std::endl; 	
	std::cin >> allWeight >> allCount;
	if (allWeight <= 0 || allCount <= 0)
	{
		std::cout << "输入的数据有误" << std::endl;
		return -1;
	}
	std::cout << "毛驴的承重能力是" << allWeight << "宝物的数量是" << allCount << std::endl; 
    std::cout << "请输入每个宝物的重量和价格"  << std::endl;
	for (int i = 0; i < allCount; ++i)
	{
		std::cin >> data[i].weight >> data[i].price;
		data[i].performance = data[i].price / data[i].weight;
	}
	//宝物更具性价比排序从高到低
    sort(data, data + allCount, compare);
	//打印排序后结构体的所有数据
	for (int i = 0; i < allCount; ++i)
	{
     	std::cout << data[i].weight << "\t" << data[i].price << "\t" << data[i].performance << std::endl;	
	}
	double sumWeight = 0, sumPrice = 0, restWeight;
	for (int i = 0; i < allCount; ++i)
	{
		if (sumWeight + data[i].weight <= allWeight) 
		{
			sumPrice += data[i].price;
			sumWeight += data[i].weight;
		}
		else 
		{
			restWeight = allWeight - sumWeight;	
			sumPrice += restWeight * data[i].performance;
			break;
		}

	}
	std::cout << "毛驴载重宝物的最大价值是" << sumPrice << std::endl;
	return 0;	
}

用类实现:

#include <iostream>
#include <algorithm>

using namespace std;

//定义数组的个数
const int M = 1000;
//宝物的结构体
struct treasure
{
	//重量
	double weight;
	//价格
	double price;
	//性价比
	double performance;
}data[M];

bool compare(struct treasure t1, struct treasure t2)
{
	return t1.performance > t2.performance;
}

class package 
{
public:
	void init();
	void resolve();
private:
	//毛驴的承重能力和宝物的数量
	int allWeight, allCount;
};

void package::init()
{
	std::cout << "请输入毛驴的承重能力和宝物的数量" << std::endl; 	
	std::cin >> allWeight >> allCount;
	if (allWeight <= 0 || allCount <= 0)
	{
		std::cout << "输入的数据有误" << std::endl;
		return;
	}
	std::cout << "毛驴的承重能力是" << allWeight << "宝物的数量是" << allCount << std::endl; 
   	std::cout << "请输入每个宝物的重量和价格"  << std::endl;
	for (int i = 0; i < allCount; ++i)
	{
		std::cin >> data[i].weight >> data[i].price;
		data[i].performance = data[i].price / data[i].weight;
	}
}

void package::resolve()
{
	//宝物更具性价比排序从高到低
    sort(data, data + allCount, compare);
	//打印排序后结构体的所有数据
	for (int i = 0; i < allCount; ++i)
	{
    	std::cout << data[i].weight << "\t" << data[i].price << "\t" << data[i].performance << std::endl;	
	}
	double sumWeight = 0, sumPrice = 0, restWeight;
	for (int i = 0; i < allCount; ++i)
	{
		if (sumWeight + data[i].weight <= allWeight) 
		{
			sumPrice += data[i].price;
			sumWeight += data[i].weight;
		}
		else 
		{
			restWeight = allWeight - sumWeight;	
			sumPrice += restWeight * data[i].performance;
			break;
		}

	}
	std::cout << "毛驴载重宝物的最大价值是" << sumPrice << std::endl;
}

int main()
{
	package pack;
	pack.init();
	pack.resolve();
	return 0;	
}

4、运行结果

请输入毛驴的承重能力和宝物的数量
10 4
毛驴的承重能力是10宝物的数量是4
请输入每个宝物的重量和价格
2 4 
2 6
4 9
6 12
2	6	3
4	9	2.25
2	4	2
6	12	2
毛驴载重宝物的最大价值是23

5、总结

如果宝物可以分割的话我们可以用贪心算法来解决,这也是常见的背包问题,如果最后一个不可以分割的话,我们不一定可以用贪心算法求出最优解,这个问题叫0-1背包问题

    原文作者:贪心算法
    原文地址: https://blog.csdn.net/u011068702/article/details/79039664
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞