PAT 1017

题目

N个用户,K个窗口。给出每个用户到达的时间,要求得出每个用户等待的平均时长。8:00才开门,17:00之后到达的客户不允许进入。

代码和思路

思路

这个题目又是一个模拟题,和前面的1014类似,只不过是侧重点不同。1014主要侧重于对于顾客进入哪个队列,客户如何分配的问题,而且只需要最后的服务时间这个结果,而本题需要的是等待时间这个过程。

  1. 题目注重于每个用户的过程,所以将结构体定义为客户。

    struct custom {
    int comeTime;
    int needTime;
    }acus;
    
  2. 这个题目将时间精度到了秒,所以将所有的时间转化为秒比较合适。就以自然时间为参考系,不要讲8:00变成0时刻点,这样自找麻烦,因为最后的平均时间是一个时间跨度问题,和0时刻取什么无关。

    int convertime(int hh, int mm, int ss) {
    return hh * 3600 + mm * 60 + ss;
    }
    
  3. 这次客户所到达的时间都不一样,所以需要针对客户进行排序(因为输入是无序时间输入)。

    bool cmp(custom a, custom b) {
    return a.comeTime < b.comeTime;
    }
    
  4. 题目中说到了,每个用户至多服务60min,所以超过60的要将其时间变为60min即3600s。

  5. 用户入窗口,是根据哪个窗口的一个人最先结束的(这就是和1014的区别,1014会先排好一部分人,其余人在黄线外,而这个题可看做黄线内的容量只有1)。

  6. 更新窗口:先找结束时间最短的窗口为下一个客户的服务窗口。
    1. 如果窗口在用户来之前空着,则该窗口的结束时间就是用户的到达时间 + 用户服务时间,但是等待时间不增加
    2. 如果用户在等待窗口,则该窗口的结束时间就是下一个用户的服务时间 + 窗口当前结束时间。

    if (windows[index] <= cus[i].comeTime) {
    		windows[index] = cus[i].comeTime + cus[i].needTime;
    	}
    else {
    	sumtime += windows[index] - cus[i].comeTime;
    	windows[index] += cus[i].needTime;
    }
    
  7. 注意输出的时候按照分钟输出,要 / 60。

整体代码

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;

struct custom {
	int comeTime;
	int needTime;
}acus;

int convertime(int hh, int mm, int ss) {
	return hh * 3600 + mm * 60 + ss;
}
bool cmp(custom a, custom b) {
	return a.comeTime < b.comeTime;
}

int n, k;
vector<custom> cus;
int windows[111];

int main() {
	float sumtime = 0.0;
	int hh, mm, ss;
	int time;
	int startTime = convertime(8, 0, 0);
	int endTime = convertime(17, 0, 0);
	scanf_s("%d %d", &n, &k);
	for (int i = 0; i < k; i++) windows[i] = startTime;
	for (int i = 0; i < n; i++) {
		scanf_s("%d:%d:%d %d", & hh, &mm, &ss, &time);
		acus.comeTime = convertime(hh, mm, ss);
		if (acus.comeTime > endTime) continue;
		if (time > 60) {
			acus.needTime = 3600;
		}
		else {
			acus.needTime = time * 60;
		}
		cus.push_back(acus);
	}
	sort(cus.begin(), cus.end(), cmp);
	for (int i = 0; i < cus.size(); i++) {
		int index = -1, min = 400000;
		for (int j = 0; j < k; j++) {
			if (min > windows[j]) {
				min = windows[j];
				index = j;
			}
		}
		if (windows[index] <= cus[i].comeTime) {
			windows[index] = cus[i].comeTime + cus[i].needTime;
		}
		else {
			sumtime += windows[index] - cus[i].comeTime;
			windows[index] += cus[i].needTime;
		}
	}
	if (cus.size() == 0) {
		printf("0.0");
		return 0;
	}
	printf("%.1f", sumtime / 60.0 / cus.size());
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值