第十四章:简单贪心

本文介绍了贪心算法的基本概念,并通过排队打水、最小等待时间、抓鱼、月饼问题、部分背包问题等实例,详细解析了贪心策略的运用。每个问题都附有算法分析和解决思路,帮助读者理解如何利用贪心法找到最优解。
摘要由CSDN通过智能技术生成

贪心入门

贪心概念

若在求解一个问题时,能根据每次所得到的局部最优解,推导出全局最优或最优目标。那么,我们可以根据这个策略,每次得到局部最优解答,逐步而推导出问题,这种策略称为贪心法。

贪心的重点:你是否知道这是一道贪心的题目,此外怎么样才是最好的贪心策略,剩下的基本交给按策略排序就可以了。接下来我们一起看几道简单的贪心类型的题目吧!

简单贪心问题

1. 排队打水问题(姚班1296)

有n个人在一个水龙头前排队接水,假如每个人的接水的时间为T_i,请编程找出一种n个人排队的顺序,使得n个人的平均等待时间最小。
假设下一个人接着打水的这个切换过程不消耗时间,且注意,每个人的等待时间包括自己接水的时间和排队等待接水的时间。(仔细审题,反正我一开始写错了)

输入输出格式

输入

第一行一个整数 nn,1≤n≤10001≤n≤1000。

第二行分别为每个人的接水时间 T_1,T_2,...,T_nT1,T2,...,Tn,用空格隔开,T_i≤10^6Ti≤106。

输出

第一行为最优的排队顺序,即编号 1 \sim n1∼n 的一种排列,每两个数字之间用空格隔开。
第二行为这种排列方案下的平均等待时间(保留两位小数)。

输入输出样例

样例

输入1

10

56 12 1 99 1000 234 33 55 99 812

输出1

3 2 7 8 1 4 9 6 10 5

532.00

【算法分析】

由于排队时,越靠前面的计算的次数越多,显然越小的排在越前面得出的结果越小(可以用数学方法简单证明,这里就不再赘述),所以这道题可以用贪心法解答,基本步骤:

(1)将输入的时间按从小到大排序;

(2)将排序后的时间按顺序依次放入每个水龙头的队列中;

(3)统计,输出答案。

重点:如何构造结构体,需要时间跟编号!

完整代码如下:

#include <bits/stdc++.h>
using namespace std;
struct water
{
    int bh;     
    int time;
};             //构造结构体
bool cmp(water a,water b)
{
    return a.time<b.time;    //按时间从小到大排序
}
water a[10005];
int main()
{
    int n;
    double d,sum=0,mus=0,avg;
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        a[i].bh=i;       //循环变量i就是编号    
        cin>>a[i].time;
    }
    sort(a+1,a+n+1,cmp);   //按时间排序
    int m=n;
    for(int i=1;i<=n;i++)
    {
        sum=sum+a[i].time*m;   //统计总时间,易错点
        m=m-1;  
    } 
    avg=sum/n;
    
    for(int i=1; i<=n; i++)
    {
        cout<<a[i].bh<<" ";
    }
    cout<<endl<<fixed<<setprecision(2)<<avg;
    return 0;
}

Copy

2. 最小等待时间(合肥市2019年第五题)姚班1648

超市的收银处有 n 位顾客在排队等着付款,他们的编号依次为 1,2,…,n。由于每个顾客所购的商品不同,因此付款时所需的等待时间也就不一样。给出这 n 个人每个人单独付款所需的时间。而顾客不同的付款顺序,所有顾客总等待时间是不一样的,收银员想知道所有顾客总等待时间最少是多少。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值