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背包问题