排队问题1
问题描述:
有n个同学在一个水龙头排队打水,每个人的打水时间是ti,请你思考,能不能找出一种排队次序,使得所有同学打完水的总时间最少
输入
共两行
第1行,排队人数n(n小于等于100)
第2行,n个数,n个人打水时所要用的时间ti(10 ≤ ti ≤ 60),两两之间用空格隔开
输出
每个人都打完水的时间总和的最小情况
样例输入
6
3 7 1 9 5 11
【样例输出】
91
策略分析:
排队打水,水龙头只有一个,很显然打水是有一个序列依次进行下去的,当排在前面的同学打水时,排在后面的同学需要等待他打完水,才能进行下一个。很显然,需要将打水时间短的排在前面先打水,这样后面的同学等待时间才是最短的,总时间也是最短的
因此
1、按照打水时间从小到大排序
2、循环进行遍历,将每一个同学的打水时间以及他的等待时间加起来
3、输出打水总时间
注意:当前同学的等待时间为他前面的所有同学的打水时间总和
因此可以考虑使用前缀和简单记录
代码
#include <cstdio>
#include <algorithm>
#define MAXN 100 + 10
int a[MAXN], b[MAXN]; //b数组记录前缀和
int main() {
int n, sum = 0;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
std::sort(a+1, a+1+n); //从小到大排序
for(int i = 1; i <= n; i++) {
b[i] += b[i-1] + a[i];
sum += a[i] + b[i-1]; //a[i]表示当前打水时间,b[i-1]表示当前等待时间
}
printf("%d\n", sum);
return 0;
}
排队问题2
问题描述:
有n个同学在r个水龙头打水,每个人的接水时间是ti,请你思考,能不能找出一种排队次序,使得所有人打水总时间最少
输入
共两行
第1行两个数,人数n,窗口数r,用空格隔开
第2行n个数,每个人看病需要的时间ti,用空格隔开
输出
所有人打完水所用的时间总和
样例输入
3 2
2 3 1
样例输出
7
策略分析:
现在水龙人升级成为了r个,那么为了使得总的打水时间最少,可以肯定的是,必须要让每一个水龙头都有同学打水才行,那么同样的道理,我们还是应该按照从小到大的顺序排序,然后每一个水龙头下面按照顺序安排一个同学,不能在第一轮打水的同学,按顺序排在每一个水龙头后面,使得每一个水龙头后面都有一个打水的序列,这样的方案才是最优的
1、按照打水时间从小到大排序
2、循环遍历,计算每一个同学的等待时间和打水时间
3、每一个水龙头进行一个求和(计算排在当前水龙头的打水总时间)
对于样例输入
水龙头编号(r) | 打水时间 | |
---|---|---|
1号 | 1 | 3 |
2号 | 2 | 无 |
因此1号的时间为1+1+3 = 5,2号的时间为2,总时间为7
代码
#include <cstdio>
#include <algorithm>
#define MAXN 500 + 10
int a[MAXN];
int main() {
int n, r, sum = 0;
scanf("%d %d", &n, &r);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
std::sort(a+1, a+1+n);
for(int i = 1; i <= n; i++) {
int t = i;
while(t >= 0) { //计算i同学的等待时间和打水时间,因为有r个水龙头因此排在他前面的那位是i-r
sum += a[t];
t -= r;
}
}
printf("%d\n", sum);
return 0;
}