算法之贪心算法

本文介绍了贪心算法的基本概念,包括其本质、实施步骤以及在购物问题中的应用。通过实例分析了简单贪心(按重量选择)和复杂贪心(按性价比选择)两种策略。提醒读者注意贪心算法仅能得到局部最优解,需满足特定前提条件。
摘要由CSDN通过智能技术生成

注:因为作者并不觉得那些专用术语对于我们正常学编程的人来说有什么用,写了也看不懂,所以本文只简单介绍了查找算法的用法,对于专业术语并没有引用

贪心算法:

本质:

利用贪心算法对问题求解时,考虑的并不是对于整体最好的策略,而是总是做出当前看来最好的选择,即贪心算法所作出的选择仅仅是在某种情况下的局部最优解

思路:

1.建立数学模型来解决问题

2.把求解的问题分解成多个子问题(类似于递归)

3.对每个子问题进行求解局部最优解

4.将数据归纳,合并成原来问题的一个解

实现框架:

while/* 或 for */(/*所写内容:向给定的总目标前进一步*/){
    
    //利用可行的策略,求解出一个可行的元素,并保存
    
}
//由所有可行的元素合成一个可行的解

注意事项:

贪心算法并不能一定得到最优解,它只是局部的最优解,所以使用贪心算法有一个大前提,就是局部的最优策略可以产生全局的最优解,除此之外,任何情况都不能完全的使用贪心算法,但有些时候可以利用贪心算法的部分思想

例题分析:

简单贪心算法:

小明去购物,想要买的食品如下,当前小明能拎回的重量不超过15斤,那么小明能拎回的食品的数量最多为?

食物牛奶面包方便面苹果饼干榴莲西瓜
重量/斤4.5123.32.86.28.4
分析思路:

想要得到最多的食品,那么利用贪心算法的策略就应该是每次都选择当前最轻的,这样最后拿到的总数才最多

实现过程:

首先对当前食品按照重量从小到大的顺序进行排序,排序结果如下

i0123456
食物面包方便面饼干苹果牛奶榴莲西瓜
重量/斤122.83.34.56.28.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;//否则就跳出循环
    }
}
复杂贪心算法:

如果这时小明想要让拎回去的价值最高,那么这个价格又是多少呢?(其他条件与上题一样)

食物牛奶面包方便面苹果饼干榴莲西瓜
价格/元1837.815.8899.220.2
重量/斤4.5123.32.86.28.4
分析思路:

根据贪心算法,现在每一次所选择的食品的价格必须是最高的,但是价格高的食物也有可能很重,所以这时我们就要考虑一个新的东西——性价比(或单价),即价格/重量,那么由此就可以按照性价比从大到小进行排序,然后按照贪心算法进行选择每一次性价比最高的食品,并进行比较,看看重量增加后是否还能拎回去

实验过程:

首先按照性价比由大到小进行排序,结果如下

食物榴莲苹果牛奶方便面饼干面包西瓜
价格/元99.215.8187.88320.2
重量/斤6.23.34.522.518.4
性价比164.843.93.232.4
i0123456

然后按照贪心策略进行选择,过程如下

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;//否则就从准备拎回去的食品的重量里删除当前食品的重量
    }
}
贪心算法(Greedy Algorithm)是一种在每一步选择中都采取当前状态下最优的选择,从而希望最终导致全局最优的算法贪心算法通常有以下特点: 1. 贪心选择性质:每一步都采取最优的选择,即局部最优解。 2. 最优子结构性质:原问题的最优解包含子问题的最优解。 3. 无后效性:每一步的决策只与当前状态有关,与之前的决策无关。 贪心算法可以用来求解一些最优化问题,如最小生成树、背包问题、活动选择问题等。 以活动选择问题为例,假设有n个活动,每个活动有一个开始时间s和结束时间f,多个活动可能在同一时间段内进行,但是同一时间只能进行一个活动。如何选择活动,使得能够安排的活动数量最多? 贪心算法的思路是:按照结束时间从早到晚排序,每次选择结束时间最早的活动,且不与已经选择的活动时间冲突。这是因为选择结束时间最早的活动,可以给后面留下更多的时间选择其他活动,从而使得总的安排活动数量最多。 参考代码如下: ``` #include <iostream> #include <algorithm> using namespace std; struct Activity { int start, finish; }; bool compare(Activity s1, Activity s2) { return (s1.finish < s2.finish); } void printMaxActivities(Activity arr[], int n) { sort(arr, arr+n, compare); cout << "Selected activities:\n"; int i = 0; cout << "(" << arr[i].start << ", " << arr[i].finish << "), "; for (int j = 1; j < n; j++) { if (arr[j].start >= arr[i].finish) { cout << "(" << arr[j].start << ", " << arr[j].finish << "), "; i = j; } } } int main() { Activity arr[] = {{1, 2}, {3, 4}, {0, 6}, {5, 7}, {8, 9}, {5, 9}}; int n = sizeof(arr)/sizeof(arr[0]); printMaxActivities(arr, n); return 0; } ``` 输出结果为: ``` Selected activities: (1, 2), (3, 4), (5, 7), (8, 9), ``` 可以看到,按照贪心算法的思路,选择了4个活动,使得能够安排的活动数量最多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值