1014 Waiting in Line (30分)

这篇博文记录下这题的解题过程,主要留由自己日后总结复习……

Input Specification:
Each input file contains one test case. Each case starts with a line containing 4 positive integers: N (≤20, number of windows), M (≤10, the maximum capacity of each line inside the yellow line), K (≤1000, number of customers), and Q (≤1000, number of customer queries).

The next line contains K positive integers, which are the processing time of the K customers.

The last line contains Q positive integers, which represent the customers who are asking about the time they can have their transactions done. The customers are numbered from 1 to K.

Output Specification:
For each of the Q customers, print in one line the time at which his/her transaction is finished, in the format HH:MM where HH is in [08, 17] and MM is in [00, 59]. Note that since the bank is closed everyday after 17:00, for those customers who cannot be served before 17:00, you must output Sorry instead.

Sample Input:

2 2 7 5
1 2 6 4 3 534 2
3 4 5 6 7

Sample Output:

08:07
08:06
08:10
17:00
Sorry

思路:模拟题,既然是排队的问题,自然想到用队列来做。
一开始构造队列的时候出了问题,犯了很多现在看来很滑稽的错误。

queue<queue<int> >q(n);
queue<queue<int> >q[n];

因为有n个窗口,所以想设n个队列,但是由于队列不支持随机访问,所以最外层定不可能用queue来存储……后来改成了:

vector<queue<int> >v(n);

还是对STL掌握的不够……(因为最简单的方法就是之间用queue型的数组,不用vector……)

然后就是按照题目所给的条件来模拟,我的方法是按照时间从8点到17点依次遍历,每次让n个队列的队首元素值减1(队列存储的是顾客办公所需要的时间),当时间为0时,说明事情处理完毕,弹出这名顾客,压入新的顾客放在队列尾部。循环过程中记得每次要判断队列是否为空,对于空队列要跳过而不是读取它的队首元素。

坑点:这点我也是看了别人的分析才明白的,题目要查询的顾客,只要在五点银行下班前排到了ta,那么ta的业务就是要处理完的并且是可查询的。我一开始以为只要在17点之后才能办完业务的顾客全输出Sorry,仔细读题目才发现是不对的。

代码如下(有逻辑错误)
(这里为了方便操作,我把时间全部化为分钟,8点是480分,17点是1020分。)

#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 1005;
struct customer {	//一开始并没有用结构体,但是仅用数组下标表示顾客编号的话会有问题
	int id;			//问题在于将顾客压入队列后,就会丢失顾客的编号,所以还是用了结构体
	int cost;
};
int main() {
	int n, m, k, q;
	customer a[maxn];
	scanf("%d %d %d %d", &n, &m, &k, &q);
	for (int i = 1; i <= k; i++) {
		scanf("%d", &a[i].cost);
		a[i].id = i;
	}
	int query[maxn];
	for (int i = 0; i < q; i++) {
		scanf("%d", &query[i]);
	}
	vector<queue<customer> >v(n);
	int served[maxn];	//这个数组用来存储顾客开始被办理业务的时间
	fill(served, served + maxn, 1030);
	int cnt = 1;
	for (int i = 0; i < m; i++)	//模仿银行8点开门时,顾客开始排队
		for (int j = 0; j < n; j++) {
			v[j].push(a[cnt++]);
			served[cnt - 1] = 480;//这里也有问题,8点开始排队并不代表此时开始办事
		}
	int time;
	int comple[maxn];	//这个数组用来存储顾客办理业务结束的时间
	fill(comple, comple + maxn, 1030);	//这里有错误
	int completed = 0;	//用来计数
	//cnt = n * m + 1;
	for (time = 480; time <= 1020; time++) {
		for (int i = 0; i < n; i++)
			if (v[i].size() != 0) {	//队列非空才能操作
				v[i].front().cost--;	//这里注意到front()返回的是队首元素的引用,所以才可以这么操作
				if (v[i].front().cost == 0) {	//办理完了则弹出
					comple[v[i].front().id] = time + 1;	//记录结束的时间
					v[i].pop();
					if (!v[i].empty())
						served[v[i].front().id] = time + 1;	//记录开始的时间
					if (cnt <= k) {		//还有顾客在黄线外的话就压入队列
						v[i].push(a[cnt++]);
					}
				}
			}
	}
	for (int i = 0; i < q; i++) {
		if (served[query[i]] >= 1020)	//这里的=号不能丢
			printf("Sorry\n");
		else
			printf("%02d:%02d\n", comple[query[i]] / 60, comple[query[i]] % 60);
	}
	return 0;
}

这段代码有好多细节上的问题以及一个逻辑上的漏洞。可是没想到居然AC了= =……问题就在

fill(comple, comple + maxn, 1030);

这句上。最后那个参数原本只要足够大即可,说明顾客的业务结束时间是在17点之后的。不知怎的,我当时莫名其妙的选择了1030这个数字,没想到正好撞上了最后一个测试点。如果你把这个改为1031,那么会显示最后一个测试点不通过 = = ……这个也是我提交通过之后才发现的,当时就觉得自己的代码并没有写完,对于17点之后的顾客没有求出ta们业务结束的时间(因为循环在17点就停止了),原来是自己瞎猫碰见死耗子了……

修改后的代码:

#include<iostream>
#include<vector>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn = 1005;
struct customer {
	int id;
	int cost;
};
int main() {
	customer a[maxn];
	int n, m, k, q;
	scanf("%d %d %d %d", &n, &m, &k, &q);
	for (int i = 1; i <= k; i++) {
		scanf("%d", &a[i].cost);
		a[i].id = i;
	}
	int query[maxn];
	for (int i = 0; i < q; i++) {
		scanf("%d", &query[i]);
	}
	int served[maxn];
	fill(served, served + maxn, 1030);
	vector<queue<customer> >v(n);
	int cnt = 1;
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			v[j].push(a[cnt++]);
			served[j + 1] = 480;
		}
	}
	int completed[maxn];
	fill(completed, completed + maxn, 9999);
	int completed_cnt = 0;
	for (int time = 481; time <= 9999; time++) {
		for (int i = 0; i < n; i++) {
			if (!v[i].empty()) {
				v[i].front().cost--;
				if (v[i].front().cost == 0) {
					completed[v[i].front().id] = time;
					v[i].pop();
					if (!v[i].empty())
						served[v[i].front().id] = time;
					if (cnt <= k) {
						v[i].push(a[cnt++]);
					}
				}
			}
		}
	}
	for (int i = 0; i < q; i++) {
		if (served[query[i]] >= 1020)
			printf("Sorry\n");
		else
			printf("%02d:%02d\n", completed[query[i]] / 60, completed[query[i]] % 60);
	}
	return 0;
}

检查了几遍,逻辑上应该是没有问题了。优化了数组的命名,还有循环时间应该从8点01开始而不是8点整。最后优化过的代码我没有加注释,思路在上面的那段中已经展现的很清楚了。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值