(涛菜菜)贪心

文章介绍了贪心思想在两种问题中的应用:主持人调度中通过排序和贪心决策确定最少主持人数量,以及三国游戏中通过贪心策略最大化让一个国家获胜的事件发生次数。
摘要由CSDN通过智能技术生成

贪心思想

贪心思想属于动态规划思想中的一种,其基本原理是找出整体当中给的每个局部子结构的最优解,并且最终将所有的这些局部最优解结合起来形成整体上的一个最优解。

1.主持人调度

有 n 个活动即将举办,每个活动都有开始时间与活动的结束时间,第 i 个活动的开始时间是 starti ,第 i 个活动的结束时间是 endi ,举办某个活动就需要为该活动准备一个活动主持人。

一位活动主持人在同一时间只能参与一个活动。并且活动主持人需要全程参与活动,换句话说,一个主持人参与了第 i 个活动,那么该主持人在 (starti,endi) 这个时间段不能参与其他任何活动。求为了成功举办这 n 个活动,最少需要多少名主持人。

数据范围:1≤n≤1e5,−2e32≤starti​≤endi​≤2e31−1

复杂度要求:时间复杂度 O(nlogn) ,空间复杂度 O(n)

具体做法:

  • step 1: 利用辅助数组获取单独各个活动开始的时间和结束时间,然后分别开始时间和结束时间进行排序,方便后面判断是否相交。
  • step 2: 遍历�n个活动,如果某个活动开始的时间大于之前活动结束的时候,当前主持人就够了,活动结束时间往后一个。
  • step 3: 若是出现之前活动结束时间晚于当前活动开始时间的,则需要增加主持人。
class Solution {
public:
    int minmumNumberOfHost(int n, vector<vector<int> >& startEnd) {
        vector<int>start;
        vector<int>end;
        //分别得到活动的起始的时间‘
        for(int i=0;i<n;i++)
        {
            start.push_back(startEnd[i][0]);
            end.push_back(startEnd[i][1]);
        }
        //分别对活动的开始和结束时间排序
        sort(start.begin(),start.end());
        sort(end.begin(),end.end());
        int res=0;
        int j=0;
        for(int i=0;i<n;i++)
        {
            //新开始的节目大于上一轮的结束时间,主持人不变
            if(start[i]>=end[j])
            {
                j++;
            }
            else {
                res++;
            }
        
        }
         return res;
    }
};

2.三国游戏

小蓝正在玩一款游戏。

游戏中魏蜀吴三个国家各自拥有一定数量的士兵 X,Y,Z(一开始可以认为都为 00)。

游戏有 n个可能会发生的事件,每个事件之间相互独立且最多只会发生一次,当第 i 个事件发生时会分别让 X,Y,Z增加 Ai,Bi,Ci

当游戏结束时 (所有事件的发生与否已经确定),如果 X,Y,Z的其中一个大于另外两个之和,我们认为其获胜。

例如,当 X>Y+Z 时,我们认为魏国获胜。

小蓝想知道游戏结束时如果有其中一个国家获胜,最多发生了多少个事件?

如果不存在任何能让某国获胜的情况,请输出 −1

输入格式

输入的第一行包含一个整数 n。

第二行包含 n个整数表示 Ai,相邻整数之间使用一个空格分隔。

第三行包含 n 个整数表示 Bi,相邻整数之间使用一个空格分隔。

第四行包含 n个整数表示 Ci,相邻整数之间使用一个空格分隔。

输出格式

输出一行包含一个整数表示答案。

//贪心,考思路
//所以,本题的贪心思路是先让A[i]−B[i]−C[i]>0的事件进一步满足题目要求,
//然后再通过A[i]−B[i]−C[i]<0的事件去进一步降低满足题目要求的可能性,
//使其达到临界点为止。这一升一降,不就使发生的事件尽可能多了嘛~
#include<bits/stdc++.h>
using namespace std;
//数据范围1e9开一个long long
typedef long long LL;
LL n,res;

void check(vector<LL>a,vector<LL>b,vector<LL>c)
{
    for(int i=0;i<n;i++)
    {
        a[i]-=b[i]+c[i];
    }
    sort(a.begin(),a.end());//对每一个事件做出的贡献从小到大排序
    LL cnt=0,sum=0;
    //越往后遍历,贡献越多,所能发生的事件也就越多
    for(int i=n-1;i>=0;i--)
    {
        sum+=a[i];
        if(sum<=0)//如果总贡献小于0就停止贡献
            break;
        cnt++;
    }
    if(cnt)
        res=max(res,cnt);
}

int main()
{
    scanf("%lld",&n);
    vector<LL>a(n),b(n),c(n);//使用vector的好处是通过函数计算时不会修改里面的值
    for(int i=0;i<n;i++)
        scanf("%lld",&a[i]);
    for(int i=0;i<n;i++)
        scanf("%lld",&b[i]);
    for(int i=0;i<n;i++)
        scanf("%lld",&c[i]);
    check(a,b,c);
    check(b,a,c);
    check(c,b,a);
    if(!res)
        puts("-1");
    else
        printf("%lld",res);
    return 0;
}

  • 10
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值