贪心算法(一)

什么是贪心算法???

贪心算法是指通过每一次都选择最优解情况,然后通过局部最优从而达到全局最优,简单理解为目光短浅,走一步看一步。

需要注意的是,贪心算法是一种思想,而非直接的方法!!!

下面我们进入具体的贪心算法中来帮助大家理解贪心其思想

一.最少硬币问题

下面我们通过leedcode上面的这题来带大家了解最简单的贪心:最少硬币问题

. - 力扣(LeetCode)

需要注意的是:

我们的钱只有三种:5 10 20

由于我们开始手里没钱,所以如果第一位顾客给的不是5元,那么直接false,如果是5元

接下来我们就需要统计我们手里的5元钱数和10元钱数,注意不需要统计20元钱数,因为20元根本不参与找钱,然后就是一边统计一边找钱,检查是否可行

贪心点:如果用户给10元我们只能找5元,但是如果用户给20元我们是有选择的,可以10+5,也可以3*5,所以这里我们优先选择10+5,就是贪心策略(保障手里的5元钱可以尽可能满足更多用户)

解题代码:

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) 
    {
        if(bills[0]!=5)
        {
            return false;
        }
        else
        {
            int five=0,ten=0;
            for(auto i:bills)
            {
                if(i==5)five++;
                else if(i==10)
                {
                    if(five==0)
                    return false;
                    else
                    {
                        five--;
                        ten++;
                    }
                }
                else
                {
                    if(ten&&five)
                    {
                        ten--,five--;
                    }
                    else if(five>=3)
                    {
                        five-=3;
                    }
                    else
                    return false;
                }
            } 
            return true;
        }       
    }
};

如果你认为选硬币就是贪心问题的话,我再带大家看一道题:

来源:洛谷

硬币问题 - 洛谷

看完题目,感觉没错就是通过局部最优,从而到全局最优情况好,现在我们来看看下面情况:

如果n==15,如果按照贪心思路,就是选11+1+1+1+1共5个硬币,但是如果选5元的只需要3个是不是就错了,实际上这题考察的是dp(动态规划)

如果你学过了dp,可以写下,但是如果你还没学,可以跳过我的代码实现:

#include<bits/stdc++.h>
using namespace std;
const int M=1e6+1;
int n;
int dp[M];
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        dp[i]=dp[i-1]+1;//注意{0,1,2,3,4,1,2,3,4,5,2,1};
        if(i>=5)
            dp[i]=min(dp[i],dp[i-5]+1);
        if(i>=11)
            dp[i]=min(dp[i],dp[i-11]+1);
    }
    cout<<dp[n]<<'\n'; 
    return 0;
}

此时的你是不是非常好奇,什么时候是贪心呢???

贪心通常有如下两种结构:

1.最优子结构性质

当一个问题的最优解包含其子问题的最优解时,则此问题具有最优子结构

2.贪心选择性质:

问题整体的最优解可以通过一系列局部最优解得到

此时我们回到第二题,发现15元钱时,选择11元并不是其子问题最优解,也无法满足性质2

关于这方面的题,我也没有找到太多,希望大家谅解!!!

找零_牛客题霸_牛客网

答案:

#include <bits/stdc++.h>
using namespace std;
int n,coin;
int main()
{
    //输入
    cin>>n;
    coin=1024-n;
    int count=0;
    //贪心
    while(coin)
    {
        if(coin>=64)
        {
            coin-=64;
            count++;
        }
        else if(coin<64&&coin>=16)
        {
            coin-=16;
            count++;
        }
        else if(coin<16&&coin>=4)
        {
            coin-=4;
            count++;
        }
        else 
        {
            coin-=1;
            count++;
        }
    }
    //输出
    cout<<count<<endl;
    return 0;
}

二.活动安排问题

该问题通常又叫区间调度问题

通常是指:

有非常的内容(例子:节目),完成这些内需要一定的时间,起始时间和结束时间给出,问如何合理安排才能尽可能安排最多的内容,或者问是否能够全部不冲突

该类问题关键在于选择策略:

我们该关注的是哪个时间:

A起始时间   B结束时间  C总共用时

很显然,我们最应该关注的是B,只有这样我们才能保证最大可能容纳更多的内容

如上图,我们关注结束时间,找最早结束时间,然后不断找在上一次结束时间之后的起始时间找最早结束时间,直到结束

以上是关于贪心算法思想的前一部分,我们之后会出关于后序内容,感谢大家的支持!!!

  • 11
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
贪心算法是一种常用的算法思想,它通常用于求解最优化问题。贪心算法的基本思想是:每一步都选择当前状态下最优的解,最终得到全局最优解。但是,贪心算法并不是所有问题都适用,有些问题需要进行证明才能确定贪心算法的正确性。 其中,反证法是一种常用的证明方法。反证法的基本思想是:假设所要证明的命题不成立,然后推导出一个矛盾的结论,从而证明原命题成立。 在贪心算法中,反证法通常用于证明贪心选择性质和最优子结构性质。具体来说,假设贪心算法得到的解不是最优解,然后推导出一个矛盾的结论,从而证明贪心算法得到的解是最优解。 举个例子,假设有一个背包问题,要求在背包容量为C的情况下,选择一些物品放入背包中,使得背包中物品的总价值最大。每个物品有两个属性:重量w和价值v。贪心算法可以选择每次选择单位重量价值最大的物品放入背包中。我们可以使用反证法来证明这个贪心算法的正确性: 假设贪心算法得到的解不是最优解,即存在一种更优的解。我们假设这个更优的解选择了物品i和物品j,但是贪心算法没有选择物品j,而是选择了物品k。那么我们可以得到以下两个不等式: v[i]/w[i] > v[j]/w[j] (物品i的单位重量价值大于物品j的单位重量价值) v[i]/w[i] < v[k]/w[k] (物品i的单位重量价值小于物品k的单位重量价值) 将这两个不等式相乘,得到: v[i]*v[k] > v[j]*w[i] 由于v[i]、v[j]、w[i]、w[j]都是正数,所以上式成立。但是,我们知道贪心算法选择物品i和物品k的总价值一定大于选择物品i和物品j的总价值,因为: v[i]*w[k] + v[k]*w[i] > v[i]*w[j] + v[j]*w[i] 这与上式矛盾,因此假设不成立,贪心算法得到的解是最优解。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猪蹄手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值