UVA 12100 打印机队列(Printer Queue, ACM/ICPC NWERC 2006)

【紫书第五章习题5-7】
算法概述:试了一下没用 STL 写,用有序对 pair 数组 q 保存每个任务的信息。第一个值类型为 bool ,当一个任务为你的任务时,该值为 true ,否则为 false 。第二个值存放优先级,范围 1~9 。
先读入全部数据,按上述形式存放在数组 q 中,并用 pos 和 pEnd 表示打印队列开始和结束的位置的后一个位置(仿照 STL 的 end() 迭代器)(数组下标),pmax为最高优先级。依照题目叙述将其转换为代码。题目要求为:
1、每次打印都是打印排在队列最前的任务。
2、如果队列中存在更高优先级的任务,不要打印当前任务,而是直接将任务移到队尾。否则,打印该任务。
先检测整个队列,记录最高优先级。然后依次读取 q[pos] 并判断是否优先级最高,如果是,则打印,计时加一分钟,清除 q[pos],并把 pos +1 ,重新查找并记录最高优先级;如果不是,则直接移到最后,代码中用 swap (头文件:algorithm)交换有序对 q[pos] 和 q[pEnd] ,并将 pos 和 pEnd 各 +1 ,即把任务移到队末。打印到自己的任务时,直接输出等待的分钟数,结束本次处理。
开始的时候 pos 和 pEnd 都是给的 unsigned char,结果过了样例但是 OJ 判错,时间 0 ms。然后想到模拟队列改动的过程中位置可能怼出 255 ,遂改成 unsigned short 。很奇怪的是当时我声明的是 q[200] ,输出中间变量发现 uDebug 上给的测试数据可以使 pos 和 pEnd 去到 400 甚至 500 以上,但是 OJ 仍然判对。
AC代码(0 ms):

#include
#include
#include
#include
#include
#pragma warning(disable:4996)
using namespace std; typedef unsigned char uchar; typedef unsigned short ushort;
pair<bool, uchar> q[65536];
int main() {
	uchar t, n, m, pmax, exitfor; ushort pEnd = 0, pos = 0, minute; scanf("%hhu", &t); //freopen("o.txt", "w", stdout);
	for (uchar i = 0; i < t; ++i) {
		for (ushort j = pos; j < pEnd; ++j)
			q[j].first = false, q[j].second = 0;
		scanf("%hhu%hhu", &n, &m); 
		for (uchar j = 0; j < m; ++j) {
			q[j].first = false; scanf("%hhu", &q[j].second); 
		}
		q[m].first = true; scanf("%hhu", &q[m].second); 
		for (uchar j = m + 1; j < n; ++j) {
			q[j].first = false; scanf("%hhu", &q[j].second); 
		}//以上:清空原有任务并输入新任务。
		//puts("TEST: END INPUT.");
		pEnd = n, pmax = 0, pos = 0, minute = 0, exitfor = 0;
		for (ushort j = pos; j < pEnd; ++j)
			if (q[j].second > pmax)pmax = q[j].second;
		for (;;) {
			if (q[pos].second < pmax) { swap(q[pos], q[pEnd]); ++pEnd, ++pos; //printf("TEST: Current task was placed to the tail. minute = %hu, pos = %hu, pEnd = %hu\n", minute, pos, pEnd);
			}//有更高优先级的任务,当前任务移至队尾。
			else {
				switch (q[pos].first) {
				case false:
					q[pos].second = 0, ++pos, ++minute;//打印该任务。
					pmax = 0; //printf("TEST: Current task was printed. minute = %hu, pos = %hu, pEnd = %hu\n", minute, pos, pEnd);
					for (ushort j = pos; j < pEnd; ++j)//重新扫描优先级。
						if (q[j].second > pmax)pmax = q[j].second;
					break;
				case true:
					++minute; printf("%hu\n", minute); exitfor = 1; 
					//printf("TEST: minute = %hu, pos = %hu, pEnd = %hu\n", minute, pos, pEnd);
					break;//自己的打印任务执行完毕,输出等待的分钟数,结束。
				}
			}
			if (exitfor == 1)break;
		}
	}
	//system("pause");
	return 0;
}

你可能感兴趣的:(ACM-ICPC)