贪心算法——排队问题

排队问题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;
}

猜你喜欢

转载自blog.csdn.net/weixin_43501684/article/details/89055004