PAT 1017 Queueing at Bank

本文通过C++实现了一个银行排队系统的模拟程序,重点介绍了如何使用排序和优先队列解决顾客排队等待时间的计算问题。文章涵盖了qsort的比较函数、动态数组定义、STL优先队列的使用技巧等内容。

完全一样的逻辑,都用了排序+priority queue,特么的Java就全错+超时!C++就过了,我干他PAT的娘!

1:qsort 的cmp 写成:

if(c1->arrTime < c2->arrTime){而不是直接return(c1->arrTime - c2->arrTime)

是为了避免

当排序的数组值很大的时候,有可能会造成溢出的问题

参见:http://blog.youkuaiyun.com/m6830098/article/details/17456263

2:动态定义数组大小:

Customer * records;

scanf("%d", &n);
	
records = (Customer *)malloc(n*sizeof(Customer));//用malloc(头文件stdlib)分配内存,记得要free,:

malloc详解参见:http://www.bccn.net/Article/kfyy/cyy/jszl/200608/4238_2.html

3:STL里的priority_queue默认是大顶堆,即倒序,与Java的PriorityQueue不同!

对于基本类型,有个简单实现顺序的方法:

priority_queue<int, vector<int>, greater<int>> windOpen;//不是PriorityQueue!,头文件是<queue>
//STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆priority_queue<int, vector<i//nt>, greater<int> >qi2;
//另外priority_queue没有Java里PriorityQueue的poll(),只能用top()+pop()实现

参见:http://www.cnblogs.com/TenosDoIt/archive/2013/04/15/3022219.html

4:char s[20];//不能用char * s,在scanf时出错,why?

单独测试也是:

//char s[] = "abc";	//都OK
char * s = "abc";	//编译OK,运行出错
	
printf("old s = %s\n",s);
	
scanf("%s",&s);

printf("new s = %s\n",s);


5:  最后一个test块为什么输出waitTime都是0?算了算了...反正不影响结果


#include <stdio.h>
#include <stdlib.h>
#include <queue>//提交PAT时要以C++文件提交
using namespace std;//干他娘的现在std又没有红线了

typedef struct{//不是类, 属性不会自动初始化为0!需手动初始化!
	int arrTime;
	int startTime;
	int waitTime;
	int proTime;
	int endTime;
}Customer;

int cmp(const void * a, const void * b){
	Customer * c1 = (Customer *)a;//转换为指针,不是对象!
	Customer * c2 = (Customer *)b;
						//
	if(c1->arrTime < c2->arrTime){//指针,所以用->
		return -1;
	}else if(c1->arrTime > c2->arrTime){
		return 1;
	}
	return 0;

}

int getTime(char * c){//fuction to convert arrive time string to seconds
	int res = 0;
	int h = (c[0]-'0')*10 + (c[1]-'0');
	int m = (c[3]-'0')*10 + (c[4]-'0');
	int s = (c[6]-'0')*10 + (c[7]-'0');
		
	res += h*3600 + m*60 + s;
		
	return res;
}


int main(){

	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);


	int i, n, k;
	double res = 0;
	Customer * records;

	scanf("%d", &n);
	scanf("%d", &k);

	records = (Customer *)malloc(n*sizeof(Customer));//用malloc(头文件stdlib)分配内存,记得要free,

	priority_queue<int, vector<int>, greater<int>> windOpen;//不是PriorityQueue!,头文件是<queue>
								//干他老母默认是倒序!所以
	//STL里面定义了一个仿函数 greater<>,对于基本类型可以用这个仿函数声明小顶堆priority_queue<int, vector<int>, greater<int> >qi2;

	int validCustCnt = 0;
	for(i = 0; i < n; i++){
		char s[20];//不能用char * s,在scanf时出错,why?
		int arrTime, proTime;
		scanf("%s %d",s,&proTime);

		arrTime = getTime(s);
		proTime *= 60;

		if(arrTime <= 17 * 3600){
			Customer c;
			c.arrTime = arrTime;
			c.proTime = proTime;
			c.endTime = 0;//手动初始化 
			c.startTime = 0;
			c.waitTime = 0;
			records[validCustCnt++] = c;
		}
	}

	qsort(records, validCustCnt, sizeof(records[0]), cmp);

	//test
	/*for(i = 0;i < validCustCnt;i++){
		Customer c = records[i];
		printf("arrive=%d  pro=%d\n",c.arrTime,c.proTime);
		printf("startTime=%d  endTime=%d waitTime=%d \n",c.startTime,c.endTime,c.waitTime);
	}*/

	for(i = 0;i < validCustCnt;i++){
			Customer c = records[i];
			
			int openTime;
			if(i < k){
				openTime = 8*3600;//first k customers start at 08:00
			}else{
				openTime = windOpen.top();//find the earliest free window
				windOpen.pop();				//priority_queue没有poll()
			}
			
			

			c.startTime =  c.arrTime < openTime ? openTime : c.arrTime;
			c.waitTime = c.startTime - c.arrTime;		

			

			res += c.waitTime;

			c.endTime = c.startTime + c.proTime;
			windOpen.push(c.endTime);

			//test
			//printf("wait=%d pro=%d\n",c.waitTime,c.proTime);
	}
		
	//test
	//for(i = 0;i < validCustCnt;i++){
	//	Customer c = records[i];
	//	printf("wait=%d pro=%d\n",c.waitTime,c.proTime);//why the waitTime is 0 here,why?????
	//}


	if(validCustCnt > 0){
			res = res/(validCustCnt*60);//seconds to minutes
	}else{
			res = 0;
	}

	printf("%.1f",res);
	
	free(records);//释放内存
	//records = NULL;//将指针指向NULL(不是null!),防止被误用
	return 0;
}


转载于:https://my.oschina.net/kaneiqi/blog/289890

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值