ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

PAT(Advanced Level)1014——模拟题又一次题面挖坑

2022-03-20 17:32:45  阅读:213  来源: 互联网

标签:PAT cur Level int 业务 ret 模拟题 服务 proc


题目传送门

一眼模拟,顾客蜂拥而至不需要考虑到达时间,无脑排队不会插队,因此不需要对服务时间进行排序之类的操作,问题已经非常简化过于友好了

proc[K]proc[K]proc[K]:每个人需要的业务服务时间
ret[K]ret[K]ret[K]:每个人业务服务进度(剩余时间)
wait[K]wait[K]wait[K]:每个人的等待时间
a[N][K]a[N][K]a[N][K]:N个队列的状态(从8:00开始)
cur[N]cur[N]cur[N]:N个队列正在服务的顾客(1~cur[i]-1是第i个队列已经服务过的顾客)

思路很简单,开门之前先把黄线以内的位置都安排好
每次都有一个业务服务时间剩余最少的人即将离开
我们只需要从每一列的当前服务对象中,找到这个 " 最快 " 的人即可
" 最快 " 的人完成业务后,就会离开银行
这时黄线后的第一个人就可以进入原先 " 最快 " 的人所在的那个队列继续等待

" 最快 " 的人完成业务时,所有队列的当前客户的业务服务进度都需要 " 前进 ",之后就重复寻找 " 最快 " 的人,让黄线外的人进入黄线

直到所有人都进入黄线在窗口前排队

那么每个人的等待时间如何计算?
想象一下当你在任何一个地方排队的时候
等待的时间只和你选择了排哪个队有关系
每当一个 " 最快 " 的人完成业务,所有人的时间都会推移,这一点其实已经体现在每个窗口当前客户的业务服务进度
换句话说,每个人等待的时间就是
所在窗口 — 排在ta前面的所有人 — 业务服务时间之和
这就可以解释我们为什么要用a[N][K]a[N][K]a[N][K]把在第iii个窗口排过队的人都记录下来

最后的输出= 排在前面的人的业务服务时间之和+自己的业务服务时间

最后一个阻碍你AC的绊脚石,就是PAT祖传的模糊描述了

刁钻测试点,都是一些题面挖的坑
测试点2和5:一个人如果开始时间在540之前(不包括540)即使结束时间超过540,依旧要服务
感谢浙大OIer提供测试数据情况

有兴趣的可以去看看其他佬的解决方案,都不错
给柳神引流了OOOooorz

Tip

数据范围看错了所有被干翻了四个点
一共就七个点,还是太着急了

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;

const int N = 1000;
const int INF = 1e9;
int K, Q, n, m;
int proc[N + 1],ret[N + 1],wait[N + 1];
int a[21][N + 1];
int ques[N + 1];
int cur[21];

int findmin() {
	int mn = INF;
	int index = -1;
	for (int i = 0; i < n; ++i) {
		if (ret[a[i][cur[i]]] < mn) {
			mn = ret[a[i][cur[i]]];   //剩余时间
			index = i;
		}
	}
	return index;
}

void mvtime(int x) {   //第x列的current顾客完成了业务,所有列的current都需要把时间推移一下
	int T = ret[a[x][cur[x]]];
	for (int i = 0; i < n; ++i) {
		ret[a[i][cur[i]]] -= T;
	}
}

void doit() {
	int index = 0;
	for (int i = 0; i < n; ++i) a[i][0] = 0;   //每一列有多少人
	for (int i = 0; i < n; ++i) cur[i] = 1;    //每一列在服务第几个人
	for (int i = 1; i <= m && index<K; ++i)    //开门时的状态
		for (int j = 0; j < n && index < K; ++j)
		{ 
			a[j][i] = ++index;   //矩阵里记录的是id
			a[j][0]++;
		}
	while (index < K) {
		int x=findmin();   //找到现在正在服务的最短时间在哪一列
		//服务完了ta就走了,x就是最短的一列,下一个人肯定就会进入x
		//接下来要把时间往后推移一下,方便之后findmin
		mvtime(x);
		a[x][0]++;
		cur[x]++;
		a[x][a[x][0]] = ++index;
	}
	//计算所有人的等待时间
	for (int i = 0; i < n; ++i) {
		int tot = 0;
		for (int j = 1; j <= a[i][0]; ++j) {
			tot += proc[a[i][j]];
			wait[a[i][j]] = tot;
		}
	}
}

void print(int T,int tt) {
	int h = T / 60;
	int min = T % 60;
	if (T-tt >= 9*60) {   //开始时间已经超过17:00
		cout << "Sorry";
		return;
	}
	h += 8;
	if (h <= 9)
		cout << "0" << h << ":";
	else cout << h << ":";
	if (min <= 9) 
		cout << "0" << min;
	else cout << min;
}

int main()
{
	cin >> n >> m >> K >> Q;
	for (int i = 1; i <= K; ++i) { cin >> proc[i]; ret[i] = proc[i]; }
	for (int i = 1; i <= Q; ++i) cin >> ques[i];
	doit();
	for (int i = 1; i <= Q; ++i) {
		print(wait[ques[i]],proc[ques[i]]);
		if (i < Q) cout << endl;
	}
	return 0;
}

标签:PAT,cur,Level,int,业务,ret,模拟题,服务,proc
来源: https://blog.csdn.net/wu_tongtong/article/details/123616021

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有