HRBUST 2223 水题

水题

Description
因为是有关于接水的问题,便简称为水题了(。

N个人排队在M个出水口前接水,第i个人接水需时为t[i],

请问接水的最短用时是多少?

Input
第一行一个整数 T ,代表有 T 组数据。

每组数据

第一行两个整数 N(<=100000) , M(<=10000) 代表有 N 个人 M 个出水口。

第二行N个整数,第i个数字t[i](<=10000)代表第i个人接水用时t[i]。

Output
对于每组数据输出一个整数,代表所需的最少接水时间。
Sample Input

2

5 3

1 2 3 4 5

6 3

1 2 3 3 4 5

Sample Output

5

6

先根据用时从小到大排下序吧,方便些;
要求花费时间最短;
那么首先我们让花费时间最长的那m个人先去接水(为什么是费时最长的先接,这样想下,两个水管,三个人,用时分别为1, 1, 3。是不是用时最多的先接,花费的时间最短)。
现在呢,我们知道哪一个水管可以先用;
那么现在我们就可以知道第一次那m个人谁会先走,所以可以直接再来m个人,接完的直接接,没接完的站在那排着队,后面那就再来m个人给他们排次队吧……
到最后,如果不够m个了,怎么办呢?那就再给剩下的几个人排一次吧。
代码就是模拟这个过程。

#include <iostream>
#include <algorithm>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cmath>
using namespace std;
#define debug(x, y) cout<<x<<" "<<y<<endl
#define nl cout<<endl
#define fy cout<<"-----"<<endl
#define PI acos(-1)
typedef long long LL;
const int maxn = 1e+5 + 10;
int main() {
    int t;
    int n, m;
    int p[maxn], w[maxn];
    ///p为每个人的接水用时,w为每个水管会被占用多长时间
    scanf("%d", &t);
    while(t--) {
        memset(w, 0, sizeof(w));
        memset(p, 0, sizeof(p));
        scanf("%d%d", &n, &m);
        for(int i=0; i<n; i++) scanf("%d", &p[i]);
        sort(p, p+n);
        int i;
        int res = 0;
        int x;
        ///模拟过程
        ///w数组按从小到大排,
        for(i=n-1; i>=m-1; i-=m) {
            for(int j=0; j<m; j++) w[j] += p[i-j];///排队的时候,费时多去前面
            sort(w, w+m);///来了m个人之后,排序,则第一个下次排队一定要走
            /*
            每排次队,让他们最少走一个人,就是有一个水龙头不排队,就可以用。
            加与不加都没啥事
            res += w[0];
            x = w[0];
            ///debug(res, 0);
            for(int j=0; j<m; j++) w[j] = w[j] - x;
            */
        }
        ///剩下的人不够m个
        if(i!=0) {
            for(int j=0; j<=i; j++) w[j] += p[i-j];
        }
        sort(w, w+m);
        res += w[m-1];
        cout << res << endl;
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值