贪心算法(Greedy Algorithm)

贪心算法思想

贪心算法,是寻找最优解问题的常用方法,这种方法模式一般将求解过程分成若干个步骤,但每个步骤都应用贪心原则,选取当前状态下最好/最优的选择(局部最有利的选择),并以此希望最后堆叠出的结果也是最好/最优的解。{看着这个名字,贪心,贪婪这两字的内在含义最为关键。这就好像一个贪婪的人,他事事都想要眼前看到最好的那个,看不到长远的东西,也不为最终的结果和将来着想,贪图眼前局部的利益最大化,有点走一步看一步的感觉。}
贪心算法的基本步骤:
步骤1:从某个初始解出发
步骤2:采用迭代的过程,当可以向目标前进一步时就根据局部最优策略,得到一部分解,缩小问题规模;
步骤3:将所有解综合起来。

示例1:找零钱问题

假设你开了间小店,不能电子支付,钱柜里的货币只有 25 分、10 分、5 分和 1 分四种硬币,如果你是售货员且要找给客户 41 分钱的硬币,如何安排才能找给客人的钱既正确且硬币的个数又最少?
这里我们需要明确的几个点:
1、货币只能25分、10分、5分和1分四种硬币;
2、找给客户41分钱的硬币;
3、硬币最少化。
思考,能使用我们今天学到的贪婪算法吗?怎么做?(回顾下贪婪算法的步骤)
1、找给顾客钱sun_money=41分钱,可选择的是25分,10分,5分和1分四种硬币。能找25分的就不找10分的原则,初次线找给顾客25分;
2、还差顾客sum_money=41-25=16。然后从25分、10分、5分和1分四种硬币选取局部最优的给顾客,也就是选10分的,此时sum_money=16-10=6。重复迭代过程,还需要sum_money=6-5=1,sum_money=1-1=0。至此,顾客收到零钱,交易结束;
3、此时41分,分成1个25分,1个10分,1个5分,1个1分,总共四枚硬币。

#include <iostream> 
using namespace std;
#define MAX 0x3f3f3f

int main(){
	int a[MAX];
	cout << "请输入所拥有的银币面值(从小到大输入):" << endl;
	cin >> ONE >> FIVE >> TEN >> TWENTYFIVE;
	int money;
	cout << "请输入你要找的金额:" << endl;
	cin >> money; 
	// 不断尝试每种硬笔
	int num25, num10, num5, num1; 
	num25=num10=num5=num1=0;
	while(money >= TWENTYFIVE){
		num25++;
		money -= TWENTYFIVE;
	} 
	while(money >= TEN){
		num10++;
		money -= TEN;
	}
	while(money >= FIVE){
		num5++;
		money -= FIVE;
	}
	while(money >= ONE){
		num1++;
		money -= ONE;
	}
	cout << "找出的25分钱的硬币数:" << num25 << endl;
	cout << "找出的10分钱的硬币数:" << num10 << endl;
	cout << "找出的5分钱的硬币数:" << num5 << endl;
	cout << "找出的1分钱的硬币数:" << num1 << endl;
	return 0;
}

示例二:背包最大价值问题

有一个背包,最多能承载重量为C=150的物品,现在有7个物品(物品不能分割成任意大小),编号为 1~7,重量分别是 wi=[35,30,60,50,40,10,25],价值分别是 pi=[10,40,30,50,35,40,30],现在从这 7 个物品中选择一个或多个装入背包,要求在物品总重量不超过 C 的前提下,所装入的物品总价值最高。
这里需要明确的几个点:
1、每个物品都有重量和价值两个属性;
2、每个物品分为被选中和不被选中两个状态(后面还有个问题,待讨论);
3、可选物品列表已知,背包总的承重量一定。
所以,我们要怎样构造这个数据结构呢?
构建描述每个物品的数据体结构 OBJECT和背包问题定义为:

//typedef是类型定义的意思
//定义待选物体的结构体类型
typedef struct tagObject{
	int weight;
	int price;
	int status;
}OBJECT;

//定义背包问题
typedef struct tagKnapsackProblem{
	vector<OBJECT>objs;
	int totalC;
}KNAPSACK_PROBLEM;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值