1026 Table Tennis (30分)

 

不得不说,这不是一道好题,很烂...(这也许就是模拟题的特点吧,考的是细心程度和debug调试能力)逻辑复杂,需要非常周全精细的考虑,需要避免的坑有很多。这种类似排队的模拟题,目前为止这是第三道(1014,1017,1026),有着大体相似的描述和思路(我回去看了看之前的记录,发现这种类型的题真的很让我头疼,我太菜了),但这题由于加了个vip制度,使得代码量剧增。可以看到通过的代码十分冗长(当然也有我自己的原因,太菜了)。约两百行的代码。第一次提交的时候得了25分,测试点5,7,8没过,原来是我漏考虑了一种情况,就是说当有多个vip桌子空出来时,选择vip桌号最小的而不是普通桌号最小的,大概是这个意思。如果能通过一下测试用例,测试点5应该就能通过:

测试用例:
4
06:00:00 30 1
08:00:00 30 1
10:00:00 30 1
12:00:00 30 1
5 1
3
输出应为:
06:00:00 08:00:00 120
08:00:00 08:00:00 0
10:00:00 10:00:00 0
12:00:00 12:00:00 0
1 0 3 0 0

我参考了别人的博客(主要看了别人的文字描述,代码真的看不下去,都太长了),想着为桌子选人可能会有漏洞,后来想重新换一个策略是,为人找桌子,不知道哪里出错了,死活跳不出循环,我又太垃圾了不会用dev进行调试,干脆放弃,在原来25分的代码基础上进行修补,然后修补了这一点得了26分...合着用了这么长时间才多拿了一分...还剩下测试点7,8。后来又试着用dev的单步调试功能,发现我一直以为出bug的部分其实没有错,错在另一部分,佛了...然后很快找到了其中的疏漏,其实我思路没有错,只是变量设置的太多了,写着写着甚至忘记了某标志的功能,应该为该标志添加判断的地方没有添加(代码中的label)。如果能通过一下测试用例,应该能通过测试点7和8:

测试用例为:
3
07:59:31 60 1
07:59:29 60 1
08:00:30 100 1
2 1
1
输出为:
1
07:59:29 08:00:00 1
07:59:31 08:00:00 0
08:00:30 09:00:00 60
2 1

虽然题目说了保证到达时间在八点到晚上九点之间,但如果代码能按照上述的测试输出一样的结果,应该就没问题了(反正我是这样的)。我的代码其实可以精简一点,变量名可以改改,可读性会更强,但我觉得这题实在没有过多的学习价值,反复的在一些题目没有明确说明的要求里设置坑点,这是pat题目的特点...有时间再补充写写思路,免得以后看自己的代码都看不懂了:

1.每个客户player拥有如下信息:到达时间arrive,被服务时间serve,等待时间wait,vip标志(如果是vip,则vip=1),使用时间P,被服务标志visited(visited=1表示该客户已经被服务过)。每张桌子table拥有如下信息:vip标志,最后一个客户结束服务的时间finish,服务客户的总数cnt。

2.两个数组Ordinary,T分别存储客户信息和桌子信息。用sort()函数根据客户的到达时间排序,得到一个客户队列(我用数组模拟队列)。

3.以“为队首找桌子”为原则,完成vip制度下的服务程序。cnt1记录着队首的位置,cnt2是未被服务的vip人数。思路如下:

如果队首被服务过,则跳过该队首,更新队首位置(下一个);

如果队首没被服务过,根据该客户是不是vip,为这个客户找合适的桌子

        如果是vip客户,则寻找编号最小的空闲的vip桌(空闲是指,客户的到达时间大于某桌子的finish),如果找到了,记下桌子编号为mintable,跳过以下两个判断;

                                  如果没有空闲的vip桌,则寻找编号最小的空闲的普通桌,如果找到了,记下桌子编号为mintable,跳过以下一个判断;

                                  如果没有空闲的桌子,则寻找最早结束服务的桌(finish最小的桌子),一定能找到这个桌子,记下桌子编号为mintable。

        如果不是vip客户,则寻找编号最小的空闲的桌子,如果找到了,记下桌子编号为mintable,跳过以下一个判断;

                                   如果没有空闲的桌子,则寻找最早结束服务的桌(finish最小的桌子),一定能找到这个桌子,记下桌子编号为mintable。

至此,我们已经为队首找到了合适的桌子,该桌子编号为mintable。此后,以“为桌子找客户”为原则。

如果这个桌子是vip桌,则需要继续在队列中寻找第一个符合条件的vip用户。条件是“该vip用户的到达时间小于等于队首的到达时间”。

                                    如果满足这个条件,则轮到该vip客户被服务;如果找不到满足这个条件的客户,则服务队首。

如果这个桌子是普通桌,则服务队首。

(在服务客户时,更新客户的信息和桌子的信息)

  1 #include <iostream>
  2 #include<cstdio>
  3 #include<vector>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 struct player{
  8     int arrive,serve,wait,vip,P,visited; 
  9     player(){
 10     arrive=serve=wait=vip=P=visited=0;
 11     }
 12 };
 13 struct table{
 14     int vip,finish,cnt;
 15     table(){
 16         vip=cnt=0;
 17         finish=28800;
 18     }
 19 };
 20 bool cmp0(player a,player b){
 21     return a.arrive<b.arrive;
 22 }
 23 bool cmp1(player a,player b){
 24     return a.serve<b.serve;
 25 }
 26 int main()
 27 { 
 28   int N,hh,mm,ss,P,vip,arrive;
 29   scanf("%d",&N);
 30   vector<player> Ordinary,Vip;
 31   player PLAY;
 32   int cnt2=0; 
 33   for(int i=0;i<N;i++){
 34       scanf("%d:%d:%d%d%d",&hh,&mm,&ss,&P,&PLAY.vip);
 35       PLAY.arrive=hh*3600+mm*60+ss;
 36       if(PLAY.arrive)
 37       if(P*60<7200)
 38          PLAY.P=P*60;
 39       else
 40          PLAY.P=7200;
 41       if(PLAY.vip==1)
 42         cnt2++; 
 43 
 44     Ordinary.push_back(PLAY);
 45   }    
 46   sort(Ordinary.begin(),Ordinary.end(),cmp0);
 47   int K,M,m;
 48   scanf("%d%d",&K,&M);
 49   vector<table> T(K+1);//vip桌信息 
 50   for(int i=0;i<M;i++) {
 51       scanf("%d",&m);
 52        T[m].vip=1;
 53   }
 54   int min,mintable;
 55   vector<player> res;
 56   int flag=0,cnt1=0;
 57   while(cnt1<N&&flag==0){
 58       if(Ordinary[cnt1].visited==1){
 59           cnt1++;
 60           continue;
 61       }
 62     int flag1=0;
 63     if(Ordinary[cnt1].vip==1){ 
 64         for(int i=1;i<=K;i++){
 65             if(T[i].finish<=Ordinary[cnt1].arrive&&T[i].vip==1){
 66                 mintable=i;
 67                 flag1=1;
 68                 
 69                 break;
 70             }
 71         }
 72         if(flag1==0){
 73             for(int i=1;i<=K;i++){
 74                 if(T[i].finish<=Ordinary[cnt1].arrive){
 75                 mintable=i;
 76                 flag1=1;
 77                 break;
 78             }
 79             }
 80         }
 81         if(flag1==0){
 82             min=T[1].finish;//找到结束时间最早的桌子 
 83               mintable=1;
 84               flag1=1;
 85               for(int p=2;p<=K;p++){
 86                  if(T[p].finish<min){
 87                   min=T[p].finish;
 88                    mintable=p;
 89                 }
 90              } 
 91           }
 92     
 93     }
 94     else{
 95         if(flag1==0){
 96             for(int i=1;i<=K;i++){
 97                 if(T[i].finish<=Ordinary[cnt1].arrive){
 98                 mintable=i;
 99                 flag1=1;
100                 break;
101             }
102             }
103         }
104         if(flag1==0){
105             min=T[1].finish;//找到结束时间最早的桌子 
106              mintable=1;
107         for(int p=2;p<=K;p++){
108               if(T[p].finish<min){
109               min=T[p].finish;
110               mintable=p;
111               }
112           }
113         }
114     }
115     int label=0;
116     if(T[mintable].vip==1&&cnt2!=0){
117         for(int j=cnt1;j<Ordinary.size();j++){//在队伍中找到第一个满足以下条件的vip 
118             if(Ordinary[j].vip==1&&Ordinary[j].visited==0&&Ordinary[j].arrive<=T[mintable].finish&&label==0)
119             {     label=1;
120                   Ordinary[j].wait=T[mintable].finish-Ordinary[j].arrive;//更新等待时间
121                   Ordinary[j].serve=T[mintable].finish;//记录被服务的时间
122                 
123                   T[mintable].finish+=Ordinary[j].P;
124               Ordinary[j].visited=1; 
125               cnt2--; 
126               if(Ordinary[j].serve>=75600)
127                 {   flag=1;
128                     break;
129                 }
130               res.push_back( Ordinary[j]);
131               T[mintable].cnt++;
132               if(j==cnt1)
133                  cnt1++;
134           }
135         }
136         
137         if(label!=1){
138         if(Ordinary[cnt1].visited==0){
139         if(T[mintable].finish>Ordinary[cnt1].arrive) { 
140           Ordinary[cnt1].wait=T[mintable].finish-Ordinary[cnt1].arrive;
141           Ordinary[cnt1].serve=T[mintable].finish;//记录被服务的时间
142           T[mintable].finish+=Ordinary[cnt1].P;
143         }
144         else
145         { Ordinary[cnt1].serve=Ordinary[cnt1].arrive;//记录被服务的时间 
146           T[mintable].finish=Ordinary[cnt1].arrive+Ordinary[cnt1].P;    
147         }
148         Ordinary[cnt1].visited=1; 
149         if(Ordinary[cnt1].serve>=75600)
150                 {   flag=1;
151                     break;
152                 }
153         res.push_back( Ordinary[cnt1]);
154         T[mintable].cnt++;
155         
156     }
157         cnt1++;    
158         }
159     }
160     else//如果不是vip桌 ,选出未被服务的队首 
161     {  
162      if(Ordinary[cnt1].visited==0){
163         if(T[mintable].finish>Ordinary[cnt1].arrive) { 
164           Ordinary[cnt1].wait=T[mintable].finish-Ordinary[cnt1].arrive;
165           Ordinary[cnt1].serve=T[mintable].finish;//记录被服务的时间
166           T[mintable].finish+=Ordinary[cnt1].P;
167         }
168         else
169         { Ordinary[cnt1].serve=Ordinary[cnt1].arrive;//记录被服务的时间 
170           T[mintable].finish=Ordinary[cnt1].arrive+Ordinary[cnt1].P;    
171         }
172         Ordinary[cnt1].visited=1; 
173         if(Ordinary[cnt1].serve>=75600)
174                 {   flag=1;
175                     break;
176                 }
177         res.push_back( Ordinary[cnt1]);
178         T[mintable].cnt++;
179         
180     }
181         cnt1++;    
182     }
183 
184   }
185   sort(res.begin(),res.end(),cmp1);
186   int temp1,temp2,temp3,temp4,temp5,temp6;
187   for(int i=0;i<res.size();i++){
188       temp1=res[i].arrive/3600;
189       temp2=(res[i].arrive-temp1*3600)/60;
190       temp3=(res[i].arrive-temp1*3600-temp2*60);
191       temp4=res[i].serve/3600;
192       temp5=(res[i].serve-temp4*3600)/60;
193       temp6=(res[i].serve-temp4*3600-temp5*60);
194       double temp7=res[i].wait/60.0;
195       printf("%02d:%02d:%02d %02d:%02d:%02d %.0f\n",temp1,temp2,temp3,temp4,temp5,temp6,round(temp7));
196   }  
197   for(int i=1;i<=K;i++){
198       if(i!=K)
199        printf("%d ",T[i].cnt);
200       else
201        printf("%d",T[i].cnt);
202   }
203   return 0;
204 }

 

posted @ 2020-03-24 01:42  wsshub  阅读(485)  评论(1)    收藏  举报