贪心算法思想
贪心算法,是寻找最优解问题的常用方法,这种方法模式一般将求解过程分成若干个步骤,但每个步骤都应用贪心原则,选取当前状态下最好/最优的选择(局部最有利的选择),并以此希望最后堆叠出的结果也是最好/最优的解。{看着这个名字,贪心,贪婪这两字的内在含义最为关键。这就好像一个贪婪的人,他事事都想要眼前看到最好的那个,看不到长远的东西,也不为最终的结果和将来着想,贪图眼前局部的利益最大化,有点走一步看一步的感觉。}
贪心算法的基本步骤:
步骤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;