算法学习之贪心法(背包问题)

China☆狼群 提交于 2019-12-22 04:09:31

贪心法介绍: 一个贪心算法总是做出当前最好的选择,也就是说,它期望通过局部最优选择从而得到全局最优的解决方案。

大体步骤:

  1. 贪心策略:制定贪心策略,并选择最佳的策略实施
  2. 局部最优解:通过策略,一步一步得到局部最优解。
  3. 全局最优解:把所有的局部最优解整合到一起,还原出原来问题的最优解。

示例如下


问题描述

假设山洞中有n种宝物,每种宝物有一定重量w和相应的价值v,毛驴运载能力有限,只能运走m重量的宝物,一种宝物只能拿一样,宝物可以分割。那么怎么才能让背包装走宝物的价值最大呢?

贪心策略

  1. 每次挑选价值最大的宝物装入背包,得到的结果是否为最优?
  2. 每次挑选重量最小的宝物装入背包,得到的结果是否为最优?
  3. 每次挑选价值单位重量价值最大的宝物装入背包,得到的结果是否为最优?

分析各策略后,我们挑选第三种策略:每次挑选价值单位重量价值最大的宝物装入背包。

思路

  1. 计算每件宝物的性价比
  2. 将宝物按性价比排序
  3. 按贪心策略依次将性价比最高的宝物放入背包
  4. 若是下一性价比最高宝物重量超过剩余背包容量,将宝物拆分后再放入背包

完整代码

#include<iostream> 
#include<algorithm>
using namespace std;

const int M = 10005;
struct three
{
	double w;  // 宝物重量
	double v;  // 宝物价值
	double p;  // 宝物性价比
}s[M];

bool cmp(three a,three b)
{
	// 按照宝物的性价比排序 
	return a.p > b.p; 
}

int main()
{
	int n;  // 宝物数量 n
	double m;  //  背包的最大载重 m
	
	cout << "请输入宝物数量 n 及背包的最大载重 m " << endl;
	cin >> n >> m;
	
	cout << "请输入每个宝物的重量 w 及价值 v " << endl;
	for(int i = 0;i < n;i++)
	{
		cin >> s[i].w >> s[i].v;
		
		// 求性价比 
		s[i].p = s[i].v / s[i].w;  
	}
	 
	// 按性价比排序 
	sort(s, s+n,cmp);

	// 装入的宝物的最大价值总和 
	double sum = 0.0;
	
	// 将宝物装入背包 
	for(int i=0;i<n;i++)
	{
		if(m > s[i].w)
		{
			m -= s[i].w;
			sum += s[i].v;
		}
		else
		{
			sum += (m*s[i].p);
			break;
		}
	}
	
	cout << "装入的宝物的最大价值总和为" << sum << endl;
	return 0; 
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!