注:因为作者并不觉得那些专用术语对于我们正常学编程的人来说有什么用,写了也看不懂,所以本文只简单介绍了查找算法的用法,对于专业术语并没有引用
贪心算法:
本质:
利用贪心算法对问题求解时,考虑的并不是对于整体最好的策略,而是总是做出当前看来最好的选择,即贪心算法所作出的选择仅仅是在某种情况下的局部最优解
思路:
1.建立数学模型来解决问题
2.把求解的问题分解成多个子问题(类似于递归)
3.对每个子问题进行求解局部最优解
4.将数据归纳,合并成原来问题的一个解
实现框架:
while/* 或 for */(/*所写内容:向给定的总目标前进一步*/){ //利用可行的策略,求解出一个可行的元素,并保存 } //由所有可行的元素合成一个可行的解
注意事项:
贪心算法并不能一定得到最优解,它只是局部的最优解,所以使用贪心算法有一个大前提,就是局部的最优策略可以产生全局的最优解,除此之外,任何情况都不能完全的使用贪心算法,但有些时候可以利用贪心算法的部分思想
例题分析:
简单贪心算法:
小明去购物,想要买的食品如下,当前小明能拎回的重量不超过15斤,那么小明能拎回的食品的数量最多为?
食物 | 牛奶 | 面包 | 方便面 | 苹果 | 饼干 | 榴莲 | 西瓜 |
---|---|---|---|---|---|---|---|
重量/斤 | 4.5 | 1 | 2 | 3.3 | 2.8 | 6.2 | 8.4 |
分析思路:
想要得到最多的食品,那么利用贪心算法的策略就应该是每次都选择当前最轻的,这样最后拿到的总数才最多
实现过程:
首先对当前食品按照重量从小到大的顺序进行排序,排序结果如下
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
食物 | 面包 | 方便面 | 饼干 | 苹果 | 牛奶 | 榴莲 | 西瓜 |
重量/斤 | 1 | 2 | 2.8 | 3.3 | 4.5 | 6.2 | 8.4 |
然后按照贪心策略进行选择,过程如下
i=0,放入后当前重量为1,不超过15,可以,现在的总数量加1
i=1,放入后当前重量为3,不超过15,可以,现在的总数量加1
i=2,放入后当前重量为5.8,不超过15,可以,现在的总数量加1
i=3,放入后当前重量为9.1,不超过15,可以,现在的总数量加1
i=4,放入后当前重量为13.6,不超过15,可以,现在的总数量加1
i=5,放入后当前重量为19.8,超过15,不可以,现在的总数量不变
i=6,放入后当前重量为22,超过15,不可以,现在的总数量不变
综上可以得知,最多可以带回去的数量为5
样例代码:
double w;//能拎动的的食品的总重量 int n,sum=0,tmp=0;//n为想买的总数量,sum为能拎回去的总数量,tmp为当前准备拎回去的食品的重量 double wg[10];//想买的每件食品的重量 sort(wg,wg+n);//按照从小到大的顺序进行排序 for (int i=0;i<n;i++){//贪心算法 tmp+=wg[i]; if (tmp<=tw){//如果当前重量小于或等于能拎动的总数量 sum++;//就将能拎回去的总数量加1 }else{ break;//否则就跳出循环 } }
复杂贪心算法:
如果这时小明想要让拎回去的价值最高,那么这个价格又是多少呢?(其他条件与上题一样)
食物 | 牛奶 | 面包 | 方便面 | 苹果 | 饼干 | 榴莲 | 西瓜 |
---|---|---|---|---|---|---|---|
价格/元 | 18 | 3 | 7.8 | 15.8 | 8 | 99.2 | 20.2 |
重量/斤 | 4.5 | 1 | 2 | 3.3 | 2.8 | 6.2 | 8.4 |
分析思路:
根据贪心算法,现在每一次所选择的食品的价格必须是最高的,但是价格高的食物也有可能很重,所以这时我们就要考虑一个新的东西——性价比(或单价),即价格/重量,那么由此就可以按照性价比从大到小进行排序,然后按照贪心算法进行选择每一次性价比最高的食品,并进行比较,看看重量增加后是否还能拎回去
实验过程:
首先按照性价比由大到小进行排序,结果如下
食物 | 榴莲 | 苹果 | 牛奶 | 方便面 | 饼干 | 面包 | 西瓜 |
---|---|---|---|---|---|---|---|
价格/元 | 99.2 | 15.8 | 18 | 7.8 | 8 | 3 | 20.2 |
重量/斤 | 6.2 | 3.3 | 4.5 | 2 | 2.5 | 1 | 8.4 |
性价比 | 16 | 4.8 | 4 | 3.9 | 3.2 | 3 | 2.4 |
i | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
然后按照贪心策略进行选择,过程如下
i=0,放入后重量为6.2,不超过15,可以,此时总价值为99.2
i=1,放入后重量为9.5,不超过15,可以,此时总价值为115
i=2,放入后重量为14,不超过15,可以,此时总价值为133
i=3,放入后重量为16,超过15,不可以,此时总价值为133
i=4,放入后重量为16.5,超过15,不可以,此时总价值为133
i=5,放入后重量为15,不超过15,可以,此时总价值为136
i=6,放入后重量为23.4,超过15,不可以,此时总价值为136
综上可知,小明能够带回去的食品的最大价值为136元
样例代码:
struct food{ double w,p,j;//w为重量,p为价格,j为性价比 }wg[10]; double k,tmp;//k能拎动的的食品的总重量,tmp为当前准备拎回去的食品的重量 int n,sum;//n为想买的总数量,sum为能拎回去的总资产 sort (wg,wg+n,cmp);//按照性价比从大到小进行排序 for (int i=0;i<n;i++){//贪心算法 tmp+=w[i].w; if (tmp<=k){//如果可以拎动 sum+=w[i].p;//就将总资产加上当前这个食品的价格 }else { tmp-=w[i].w;//否则就从准备拎回去的食品的重量里删除当前食品的重量 } }