IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> PAT ( Advanced Level ) 1014——模拟题又一次题面挖坑 -> 正文阅读

[C++知识库]PAT ( Advanced Level ) 1014——模拟题又一次题面挖坑

题目传送门

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

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

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

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

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

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

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

最后一个阻碍你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;
}
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-21 20:30:29  更:2022-03-21 20:31:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:25:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码