1014 Waiting in Line (30分)

这题好难的。。想了很久怎么处理,参考了别人的代码,发现一个测试点的疏漏,pat的测试点给的还不是很全面。自己原来的代码就不提了,很垃圾,只过了测试点1拿了12分,还有两个测试点超时,其他测试点答案错误...我还想了好久...太菜了。学习别人的思路,自己改动了一些地方。
1.构造结构体Que,成员有lastend和q,lastend记录每一队的最后一个人的结束时间,q是队列,记录队列每个人的服务时间。lastend的巧妙之处在于,可以通过他判断有人新入队时是否已经超过了17:00。很多人多设置了一个poptime记录队首结束服务的时间,其实没有必要,直接访问队首即可(在队首出队时要对新的队首的服务时间进行更新)
2.pat给的测试点,可能可以概括为一种情况,一定是第一队的队首率先结束服务,我在csdn上找了一份代码,不能正确处理其他队的队首率先服务完毕的情况(这关系到新入队的人应该去哪里排队,直接影响到新入队的人的结束服务时间),然而没考虑到这种情况的代码也能拿满分,说明pat的测试点给的不够全面。
3.如何让在黄线外的人正确入队?策略是,比较每个窗口的队首的结束服务时间,最小的应该先出队,让黄线外的人入这一队,每次仅仅一人出队,也仅仅只有一人入队,即使有人结束服务时间相同,也可以正确处理这个先后顺序。进入黄线内(已经正确入队)的人,结束服务时间就已经确定了。我之前想设置一个共同的时钟,每一队都参照这个时钟出队入队,太麻烦,并且要考虑太多特殊情况,不应该采取这种思路。每个队伍中的人结束服务的时间,仅仅取决于队伍前面的人的服务时间,不要考虑其他队的情况。
4.17:00前还没开始服务的人标记为sorry,17:00前开始服务的人,不管服务时间有多长,都得输出结束服务的时间。
1 #include<iostream> 2 #include<vector> 3 #include<cstdio> 4 #include<queue> 5 #define inf 0x3f3f3f3f 6 using namespace std; 7 struct Que{ 8 int lastend; 9 queue<int> q; 10 Que(int l=0):lastend(l){} 11 }; 12 int main(){ 13 int N,M,K,Q,cnt=1; 14 scanf("%d%d%d%d",&N,&M,&K,&Q); 15 // Que window[N+1]; 16 // int sorry[K+1]={0},据说这样申请数组不好,得用以下方式? 17 vector<Que> window(N+1);//N个窗口 18 vector<int> sorry(K+1,0); //K个标志,记录是否输出sorry 19 vector<int> time(K+1,0); 20 vector<int> res(K+1); 21 for(int i=1;i<=K;i++) 22 { 23 scanf("%d",&time[i]); 24 } 25 for(int i=1;i<=M;i++)//一行行处理 26 { for(int j=1;j<=N;j++) 27 { 28 if(cnt<=K) 29 {if(window[j].lastend>=540)//如果插入前,队伍的最后结束时间超过17:00,则后面插入的应输出sorry 30 sorry[cnt]=1; 31 window[j].q.push(time[cnt]); 32 window[j].lastend=window[j].lastend+time[cnt];//更新队伍的最后结束时间 33 res[cnt]=window[j].lastend; 34 cnt++; 35 } 36 } 37 } 38 int temp; 39 while(cnt<=K){ 40 int minwindow=1;//假设第一个窗口最先结束队首业务 41 int min=window[1].q.front();//这里有个小问题注意 42 for(int i=2;i<=N;i++){ //别人的处理使得第一个窗口的第一个人始终最先被服务完 43 if(window[i].q.front()<min){ 44 minwindow=i; 45 min=window[i].q.front(); 46 } 47 } 48 temp=window[minwindow].q.front();//队首出队前保存这个值 49 window[minwindow].q.pop();// 队首出队 50 if(window[minwindow].lastend>=540)//如果入队前,队伍的最后结束时间超过17:00,则后面插入的应输出sorry 51 sorry[cnt]=1; 52 window[minwindow].q.push(time[cnt]); 53 window[minwindow].lastend= window[minwindow].lastend+time[cnt]; 54 res[cnt]=window[minwindow].lastend; 55 window[minwindow].q.front()=temp+window[minwindow].q.front();//入队后才更新队首结束时间 56 cnt++; 57 } 58 int num,HH,MM; 59 for(int i=0;i<Q;i++) 60 { scanf("%d",&num); 61 if(sorry[num]) 62 printf("%s\n","Sorry"); 63 else 64 { 65 HH=(res[num]+480)/60;MM=(res[num]+480)%60; 66 printf("%02d:%02d\n",HH,MM); 67 } 68 } 69 return 0; 70 }
自己写的代码,12分,没有学习的价值...自己再写一遍都可能复现不了这样的思路...如下:
1 #include<iostream> 2 #include<vector> 3 #include<cstdio> 4 #include<queue> 5 using namespace std; 6 queue<int> Que[21]; 7 queue<int> waiting; 8 int N,M,size; 9 int serve(int start,int T){ 10 if(start>=1020||start<0) 11 return -1; 12 else 13 return start+T; 14 } 15 void pick(){ 16 int min=Que[0].size(); 17 int k=0; 18 for(int i=0;i<N;i++) 19 if(min>Que[i].size()) 20 { min=Que[i].size(); 21 k=i; 22 } 23 for(int i=0;i<N;i++) 24 if(min==Que[i].size()&&!waiting.empty()) 25 {Que[i].push(waiting.front()); 26 size++; 27 waiting.pop(); 28 } 29 } 30 int main(){ 31 int K,Q,time; 32 scanf("%d%d%d%d",&N,&M,&K,&Q); 33 if(K>=N*M) 34 size=N*M; 35 else 36 size=K; 37 int cus_time[2020]={0}; 38 for(int i=1;i<=K;i++) 39 {scanf("%d",&time); 40 cus_time[i]=time; 41 } 42 for(int i=1,j=0;i<=N*M;i++) 43 Que[(j++)%N].push(i); 44 for(int i=N*M+1;i<=K;i++) 45 waiting.push(i); 46 47 int res[2020]={0}; 48 int now=480; 49 int min; 50 int m; 51 while(size!=0){//当还有人在排队时,继续 52 for(int i=0;i<N;i++)//假设第一个非空队伍的队首为最早结束 53 {if(!Que[i].empty()) 54 {min=serve(now,cus_time[Que[i].front()]); 55 m=cus_time[Que[i].front()]; 56 break; 57 } 58 } 59 for(int i=0;i<N;i++){//这个循环作用是,找到所有队首的结束时间(这个时间记为min)最早的队伍(可能不止一队) 60 if(!(Que[i].empty())&&(min>serve(now,cus_time[Que[i].front()]))) 61 { 62 min=serve(now,cus_time[Que[i].front()]); 63 m=cus_time[Que[i].front()]; 64 } 65 } 66 for(int i=0;i<N;i++)//这个循环的作用是,最早结束的队首出队(可能不止一队),同时更改当前时间 67 { 68 if( !(Que[i].empty()) ) 69 if(min==serve(now,cus_time[Que[i].front()]) ) 70 { now=serve(now,cus_time[Que[i].front()]); 71 res[Que[i].front()]=now; 72 Que[i].pop(); 73 size--; 74 }//如果不是最早出队的,需要更新业务处理时间 75 else 76 cus_time[Que[i].front()]=cus_time[Que[i].front()]-m; 77 } 78 pick();//当有人出队(不管是一人还是几人),仅仅令等待队伍中的一人进队 79 } 80 int num,HH,MM; 81 for(int i=0;i<Q;i++) 82 { scanf("%d",&num); 83 if(res[num]<0) 84 printf("%s\n","Sorry"); 85 else 86 { 87 HH=res[num]/60;MM=res[num]%60; 88 printf("%02d:%02d\n",HH,MM); 89 } 90 } 91 return 0; 92 }
有缺陷的代码,不能正确处理上面第2点的情况,但仍可以拿满分:
1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 struct node{ 7 int poptime, endtime;//队首的人出队(结束)时间 队尾的人结束时间 8 queue<int> q; 9 }; 10 int main() 11 { 12 //n个窗口(n<=20) m为黄线内最大容量(m<=10) k个顾客(k<=1000) q为要查询的顾客人数(q<=1000) 13 int n, m, k, p, index=1; 14 scanf("%d%d%d%d", &n, &m, &k, &p); 15 vector<int> time(k+1), result(k+1);//顾客办理业务所需时间 顾客办理业务结束时间 16 for(int i=1; i<=k; i++) 17 scanf("%d", &time[i]); 18 vector<node> window(n+1);//n个窗口n个队 19 vector<bool> sorry(k+1, false); 20 //处理开始就在黄线内顾客 前面m*n 21 for(int i=1; i<=m; i++){ 22 for(int j=1; j<=n; j++){ 23 if(index <= k){ 24 window[j].q.push(time[index]); 25 if(window[j].endtime >= 540)//队尾的人结束时间超过下午五点 26 sorry[index] = true; 27 window[j].endtime += time[index]; 28 result[index] = window[j].endtime; 29 index++; 30 } 31 } 32 } 33 //开始无法排进黄线内 m*n以后的人 34 while(index <= k){ 35 int minPoptime=window[1].poptime, minWindow=1; 36 for(int i=2; i<=n; i++){//寻找最先有人出来的窗口 37 if(window[i].poptime < minPoptime){ 38 minPoptime = window[i].poptime; 39 minWindow = i; 40 } 41 } 42 window[minWindow].q.pop();//出队一个 43 window[minWindow].q.push(time[index]);//入队 44 window[minWindow].poptime += window[minWindow].q.front();//更新队首结束时间 45 if(window[minWindow].endtime >= 540) 46 sorry[index] = true; 47 window[minWindow].endtime += time[index];//更新队尾结束时间 48 result[index] = window[minWindow].endtime;//记录该顾客结束时间 49 index++; 50 } 51 for(int i=1; i<=p; i++){ 52 int check; 53 scanf("%d", &check); 54 int temp = result[check]; 55 if(sorry[check] == true) 56 printf("Sorry\n"); 57 else 58 printf("%02d:%02d\n", (temp+480)/60, (temp+480)%60);//480 早上八点 59 } 60 return 0; 61 }
来源:https://blog.csdn.net/whl_program/article/details/77687337

浙公网安备 33010602011771号