排队打水(贪心)

题目:排队打水(贪心)

题意:

n 个人排队到 1 个水龙头处打水,第 i 个人装满水桶所需的时间是 ti,请问如何安排他们的打水顺序才能使所有人的等待时间之和最小?

输入格式

第一行包含整数 n

第二行包含 n 个整数,其中第 i 个整数表示第 i 个人装满水桶所花费的时间 ti

输出格式

输出一个整数,表示最小的等待时间之和。

数据范围

1≤n≤1e5,
1≤ti≤1e4

输入样例:

7

3 6 1 4 2 5 7

输出样例:

56

样例解释:

按 1 2 3 4 5 6 7的顺序排列,则等待的时间是1 + 3 + 6 + 10 + 15 + 21 = 56。

题目分析:贪心,设排列的顺序为a1, a2, a3, ......, an。则a1要被等n – 1次,a2要被等n – 2, ...... ,an要被等0次。即ai要被等n – i次,所以排越前面权重越大。

解题步骤:

  1. 将所有人按装水时间ti从小到大排序。
  2. 累加每个人前面所有人的装水时间。

贪心策略证明:

  1. 设贪心得出的答案是cnt,本题的正确答案是ans。
  2. 由于本题的答案ans是所有方案的最小值,所以必有ans <= cnt。
  3. 设在正确答案中有排列顺序有i < jai > aj,则我们可以交换aiaj的位置,交换后,数值小的点权重变大,数值大的点权重变小,且ai和aj的权重改变量是相等的,所以交换后能够得到更小的答案。故有cnt <= ans。
  4. 由于ans <= cntcnt <= ans,得cnt = ans。

AC代码:

#include<iostream>

#include<algorithm>

#define ll long long

 

using namespace std;

const int N = 1e5 + 10;

int a[N], n;

 

void solve(){

    scanf("%d", &n);

    for(int i = 1;i <= n;i++) scanf("%d", &a[i]);

    sort(a + 1, a + 1 + n);

    

    ll cnt = 0, res = 0;

    for(int i = 1;i <= n;i++){

        if(i >= 1) res += cnt;

        cnt += a[i];

    }

    printf("%lld\n", res);

}

 

int main(){

    solve();

    

    return 0;

}

时间复杂度:O(NlogN)。

空间复杂度:O(N)。

posted @   思丶君  阅读(204)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示