贪心算法学习——例题+思路+代码

贪心算法的定义:
贪心算法是指在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性即某个状态以前的过程不会影响以后的状态,只与当前状态有关
解题的一般步骤是:
1.建立数学模型来描述问题;
2.把求解的问题分成若干个子问题;
3.对每一子问题求解,得到子问题的局部最优解;
4.把子问题的局部最优解合成原来问题的一个解。

 例题1:区间选点

题目链接:905. 区间选点 - AcWing题库

不在活动内可能提交不了代码,也看不了题目,这里把题面切图出来,主要讲一下思路,和为什么能用贪心来写。

题面:

 

思路

1)将每个区间按右端点从小到大进行排序

2)从前往后一次枚举每个区间

     如果当前区间中已经有包含点,这直接pass

     否则,选择当前区间的右端点

如下:选第一个区间的右端点,第二、三个区间也包含此点。

选第四个区间的右端点,第五个区间也包含此点。

由此可见只需要两个点。

 看似取得是每一步的最优取法,其实是可以证明此取法就是总体最优解。

假设答案就是ans,我们算出的取法是cnt。

想一下要证明cnt就是等于ans的,可以先证明ans<=cnt,在证明ans>=cnt,就能推出ans=cnt了。

(1)由于ans是所需的点的最小数量,cnt是依次枚举每个区间选出来的点数,肯定ans<=cnt

(2)如果当前区间包含了此点,则不在此区间选点。若区间不包含此点,则选此区间的右端点。

 每个区间都是2)中否则的情况。也就是我们找到了cnt个区间之间没有任何交集的情况,此时ans>=cnt

 由此可以推出:cnt=ans。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int N=1e5+10;
struct range
{
    int l,r;
}a[N];
bool cmp(struct range&x,struct range&y)
{
    return x.r<y.r;//右端点按从小到大顺序排序
}
signed main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>a[i].l>>a[i].r;
    sort(a,a+n,cmp);//每个区间按右端点排序
    int ans=0,ed=-2e9;//最开始右端点初始值赋值为负无穷
    for(int i=0;i<n;i++)
    {
        if(a[i].l>ed)
        {
            ans++;
            ed=a[i].r;
        }
    }
    cout<<ans<<endl;
    return 0;
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值