去年Final在上海举办时我已经退役,所以没有参加。不过我当时看了比赛的直播,并也看了一下题目。我刚刚又重新看了一下题目,写了一篇对题目算法的简要分析,在此与大家探讨。
Problem A
这是一道难题,比赛中几乎所有的队避开了这题。虽说是一个模式识别,但图像可以放大,非常不好处理。可以根据pattern中平行线段间的距离来确定放大的倍数,然后再到图里面进行枚举匹配。但不仅要分情况讨论,还要注意精度。是一道算法和编程都十分繁琐的题目。
Problem B
本题是一个典型的综合题。模型本身是一个最短路,但加入了计算几何的背景。最短路的计算对于参加World Final的选手自然是小菜一碟,但此题中每条边的cost是什么?由题目的描述可知,每条边的cost是穿过的cell的个数。那么cell由什么来划分?每个tower对应的cell就是一个离这个tower比离其它tower都要近的区域。这样的区域是什么?学过计算几何的可能知道,所有的cell构成的一个平面划分是一个Voronoi图,Voronoi图可以在O(nlogn)的时间里求出。所以本题划分为两个步骤:一是求出Voronoi图并计算每条边的费用,二是计算最短路。
难点在于,Voronoi图的计算非常繁琐,我相信没有一支队愿意在比赛中写一个求Voronoi图的程序,所以我们要换一种方法。关键在于,怎样判断一个线段是否穿过了一个cell?每个cell都是一些由中垂线围成的凸多边形,如果穿过了这个cell,就必然会有交点,而这个交点一定是该线段和某条中垂线的交点。所以问题立刻变得简单:要计算线段AB是否穿过tower Pi的cell,只需要枚举PiPj的中垂线和AB的交点,再判断这个交点是否离Pi比所有其它Pj都近,如果存在这样的交点,则AB穿过Pi的cell。
这样子我们只需要一个求线段交点的routine