C++ 贪心算法-接水问题 算法自我理解A.A

题目简介:有n人需要接水,它们每个人的接水时间不一样,且有r个水龙头.

个人简介:在使用贪心算法时,最重要的是先找到策略然后解决题目.

==__==__==__==代码如下:

//代码-接水问题
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
    int a[510] = { 0 };
    int r, n, s = 0; //s为打水总时间
    cin >> n >> r; // 人数 水龙头数
    for (int i = 1; i <= n; i++) {
        cin >> a[i]; // 从1开始记录(位) 打水的时间 
    }
    sort(a + 1, a + n + 1); //从第一位开始到最后一位 从小到大排序
    for (int k = 0; k <= n; k++) {
        if (k >= r + 1) { // 因为前r个人不需要排队 因为有r个水龙头 他们可以直接打
            a[k] += a[k - r]; // 核心公式就是 a[k] = a[k] + a[k-r]
        }
        s += a[k]; // 增加总时间
    }
    cout << s << endl; //输出总时间
    return 0;
}

解析:我们先获取必要的数据,然后理解它们接水的策略,从小到大排列的目的是让它们在正向循环中都找到“最短时间”,注意:贪心算法不总是最优的.,而后通过Sort方法,它来源于头文件algorithm,将它们从小到大排列.

  为什么 需要从小到大因为这牵扯到贪心算法(每一步选择中都采取在当前状态下最好或最优(即最有利)的选择,从而希望导致结果是全局最好或最优的算法)

假设有5个人,3个水龙头,那么从小到大排列好后,第一个人就默认去第一个水龙头,于是s+=a[k],而后直到第四个人,这个时候根据贪心算法,我们会把它安排到第一个水龙头,所以就会符合条件k>=r+1,这个时候K=4我们代入到a[k]+=a[k-r]中,即 a[4] = a[4] + a[4-3] 也就是 a[4]+a[1] ,这也是到第四人的时候所需要增加的时间,同理 第七个人就是a[7] + a[7-3] 也就是a[7] + a[4]。

综上,我们可以发现3个水龙头下,速度用时按低到高排列的第1,4,7人使用了第1个水龙头(这里的第七人请不要随意牵扯到刚才给出的5人例子里,我想也不会有人瞎联想的哈哈哈)

所以第1,4,7人的时间用时为 a[1]  +  a[4]+a[1]  + a[7] + a[4] + a[1]

然后这里部分人可能又会搞混,请注意当满足k>=r+1的条件之后,a[4]被重新赋值了,所以a7的用时为a[7] + a[4] + a[1] , 注意看后面的 a[4] + a[1] 其实就是原a[4]符合条件后被重新赋值的时间.

抽象解析:如果你没懂上面的表达(笔者也是初学者,表达没有那么言简意赅)

第一个人用时2分钟 在一号水龙头接水

第四个人(它的速度是4分钟)来了,排在一号水龙头接水,因为第一个人在抽,所以它要等待的时间是2分钟他要抽水的时间是4分钟,所以共用时 2+4=6分钟.

第七个人来了!(他的速度是6分钟),他也是使用一号水龙头,排在第四个人后面,而此时第四个人它总共用时的2+4=6分钟就成为了第七个人的等待时间,所以第七个人完事儿要6+6=12分钟.

所以这3个人接水总时间为 2 + 6 + 12 = 20分钟.

如果你看懂了上面的抽象解析,那么我们把问题重新回到 有多个人 多个水龙头↓

假如有3个人 2个井 速度分别是2 4 6 那么:

前2个人自动分配2个井 用时 2+4 = 6 分钟 , 第三个人则被分配到第一个水龙头接水,所以用时 2+ 6 = 8 分钟 

所以总共用时 2 + 4  + 2+6 = 14分钟

看到这里,你就会理解为什么要从小到大排序了
因为: 比如有2个人 速度分别为 2  4 且1个水龙头

那么 1号先接水2号次之的时间为 2 + 2+4

反之 2号先接水1号次之的时间为 4 + 4+2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值