记一道坑了我三天的题——PAT甲级-1026. Table Tennis (30)

本来也没有写题解的习惯,然而这道题真是太恶心了,折磨了我快三天,所以写出来吐槽下,要是考试遇见这种题我就直接打个表投降得了。

首先要吐槽的是这种题不给说清楚题意,不说清楚也就算了,还只给一个样例,这大概就是女人心海底针?真是给陈越姥姥跪了。

在没看大佬们的解法之前,自己先写了个200行的解法(真是愚蠢啊):

用两个vector:usu和vip分别存所有的客人以及VIP客人,之后按到来时间sort一下。

把桌子包成结构体,扔到set里,重写“<”运算符:结束时间为第一关键字,id为第二关键字,这个set要动态更新(事后想想根本没必要搞个set,最多才100个桌子)。

然后循环,每次处理usu最前(一下简称队首)的客人,根据set中头一个桌子的结束时间与队首客人到来时间的关系判断客人到来时是否有空桌子:

一、有空桌子,则接下来根据队首在set的所有空闲桌子中找一个合适的桌子。

1、队首是VIP,则优先找一个id最小的vip桌子;没有的话就找个id最小的。

2、队首是普通,找个id最小的。

二、没有空桌子,队首需要等待,按照set中头一个桌子的种类进行讨论。

1、set头一个是VIP桌,需要判断下是否可以将其分给vip队列中头一个VIP客人。

2、set头一个是普通桌,直接分给队首的客人。

上述操作时要注意标记,尤其是对VIP客人操作后,usu队列中要根据标记跳过对应的VIP。

写完之后交了一发,错了一多半233,测试点1、2、6、7、8总是过不去。然后因此debug了两天,但没什么进展,看大佬们的代码,感觉也和我的结果一样。然后摆在我面前的就两条路,一是根据大佬们的方法,从新实现一遍(毕竟自己写的又臭又长);二就是拿到PAT后台的测试用例(怎么拿到?就是疯狂提交,这里想起了信安课上讲到,系统的一类安全隐患就是提供的信息太多)。然后我选择后者,毕竟不知道自己代码错在哪的感觉真的让我寝食难安。经过约100次的提交,套出了第二个测试用例(见代码开头第一个测试用例)。结果发现我TM结果和AC代码结果一样诶!然后就觉得是实际环境不同,有可能是输出的问题,就把第263行等待时间的输出从printf(“%.0lf”,(double)(cus[i].sum1-cus[i].sum0)/60)改成了AC代码中的printf(“%d”,(int)((cus[i].sum1 - cus[i].sum0) / 60.0+0.5)),然后就过了1、2、6,醉了。

输出格式这么玄学的吗?

其实这里有两点要注意:

1、该题输出格式中The waiting time must be rounded up to an integer minute(s).与平时见到的如第1011题中的the maximum profit accurate up to 2 decimal places.这两者的要求是有区别的,即四舍五入精确到是不同的两个概念。

2、精确到x位用“%.xlf”控制即可,而四舍五入一定要谨慎处理(建议手写),只用“%.xlf”是不可靠的,其并非完全根据第x+1位进行四舍五入,但也不是简单的截取。比如1011的样例(如下),在我的电脑上跑的结果就是37.97而不是37.98,但是代码仍能AC。

Sample Input

1.1 2.5 1.7

1.2 3.0 1.6

4.1 1.2 1.1

Sample Output

T T W 37.98

但还剩7、8没过。我把第200行到204行注释掉,再交一遍,就AC了。

注释掉的这一块儿其实很有意思,我写的这一段实现的效果其实是:当有桌子释放而当前有等待的客人时,会有多个桌子同时被释放的情况,此时考虑是否有VIP桌子被释放,且有VIP客人在等待,如果是这样,则把该VIP客人分配给同时释放出的VIP桌子。上述情况又包含着如下一种子情况:队首是VIP客人,正在等待,而释放出多个桌子,其中还含有VIP桌子,但首先处理(实际是指针指向)的桌子(由于其序号较小)是普通桌子。这时不注释掉那一段代码的话,结果将是VIP客人分配给VIP桌(而且是VIP桌子中序号较小的);注释掉就变成VIP客人分配给普通桌。可能有点绕,不懂的可以考虑这一样例:

3

08:00:00 10 0

08:05:00 5 0

08:08:00 10 1

2 1

2

首先需要强调的是,我的解法中“一、1、”与上述情况(实际是“二、2、”中的一部分)是不同的。那么到底该采取哪种策略呢?是类似于“一、1、”,选VIP桌;还是选序号更小的普通桌?是该注释掉那一段;还是不该注释掉?当然结果之前已经说了,注释掉才能AC,而且在上述样例下,这位大佬柳婼的代码与我注释掉的版本结果相同。那正确的策略就是选普通桌咯?不幸的是,我看到了另一个大佬Yost的代码,其中他的策略是这样的:

开始循环给每个客户“找桌子”,每次循环处理一个客户

如果这是个坑爹的vip客户

如果这个坑货到的时候没有空桌子,就需要等待最早空出的那个桌子(注意可能有多个桌子同时空出来)

如果最早有空桌子出来的时候有多个空桌子空出来,有vip桌时安排以vip桌,无vip桌则选择编号最小的那个空桌子

很明显,他选的是VIP桌,他确实也是这么做的,因为他的代码在那个例子下和我的注释掉的版本以及柳婼的结果不同,但是,他的代码也能AC。

总结一下:

A组:我的注释掉版本的代码与柳婼的策略以及在上述测试用例下结果相同,均能AC。

B组:我的未注释掉版本的代码与Yost的策略以及在上述测试用例下结果相同,我的WA在7、8,他的能AC。

A、B两组策略不同,而且结果不同,人家能过,我过不了。

总之,很扎心,真是令人窒息的操作,再给陈越姥姥跪一波。

除此之外还有几个要注意的点,就不再赘述了,认真读读题应该能get到,毕竟与上述的巨坑相比,基本算不上是坑。

你可能感兴趣的:(记一道坑了我三天的题——PAT甲级-1026. Table Tennis (30))