水题
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;
}