您的位置:首页 > 其它

2005年第29届ACM ICPC世界总决赛的试题解析

2006-04-02 22:49 567 查看
去年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即可,比起求Voronoi图,编程复杂度大大下降。而算法的时间复杂度也是可以接受的。

Problem C
虽然本题叫做Traveling Judges Problem,但却并不是一个TSP模型。仔细看一下就会发现这是一个Steiner Tree的模型,即给出一些Steiner节点,求一棵费用最小的连接所有Steiner点的树。Steiner Tree problem本是NP-hard,但此题最多20个点,规模甚小。
一般的搜索会超时,正确的做法是状态空间dp,即用一个二进制串标记各点的状态,这是topcoder中常用的技术了。

Problem D
这题首先要确定可能shuffle的次数。每次shuffle最多伴随一次交换,从而最多改变两个位置的数,因此n次shuffle后最多有2n个位置的数字不对。我们可以将得到的串跟n次shuffle不加交换的串相比较,如果不匹配的位置<=2n的话,那么n就是一个可能的shuffle次数。这样的n如果存在必然唯一。因为n<=10,所以不匹配的地方最多20个,也就是匹配的位置最少有32个。如果n1和n2同时满足匹配的位置>=32,那么公共匹配的位置就>=32+32-52=12。而不难验证,没有两个n对应的序列有超过12个位置的数字相同。
确定了shuffle的次数后,下一个难题就是如何确定交换的位置。可能的状态数呈几何级数增长,n次交换后最多可能产生52^n种不同的置换,枚举是不可能的。一种立刻出现的想法是用空间换时间,枚举m步之后可以得到的所有状态,存在一个hash table里面,然后对剩下的步数进行反向搜索再到hash table里面查找。这样子状态数下降到52^5,但仍然太大了,空间上难以承受。
我认为此题应该搜索剪枝。首先先考虑没有交换的情况,找出k次shuffle后的位置表。从这张表我们就可以知道,第i步的一次交换其实等价于第j步的某两个位置交换。这样子我们避免了对整个序列shuffle,而只用考虑交换产生的影响。
比如,第一次shuffle后,如果我们交换位置0和位置1,也就是说数字26和0,这其实等价于交换第二次shuffle后的位置1和位置3。假如我们已经求出shuffle总次数是k,那么问题就变成,每一次shuffle对应了51个对换和一个恒等置换,能否从k次中各取出一个对换,使得这些对换的乘积成为一个已知的置换。
不进行剪枝的话,运算量最多是52^10,难以承受;但每一步最多纠正两个位置,所以还剩t次shuffle的时候,如果错误的位置>2t,就可以回溯了。大部分的对换都会增加出错的位置。最坏的情况是shuffle=10而且错误的位置很少,此时平均5步之后也可以剪枝了,时间上可以承受。更强的一个剪枝是考虑轮换,一个k-轮换至少分解成k个对换的乘积,所以至少需要k次shuffle。搜索的时候,不要记录整个需要的置换,而是记录成不相交的轮换的积。这样一来节省了置换乘法的开销,二来方便剪枝。
由于我不知道具体数据如何,从而无法得知此算法是否能通过所有数据。如果还不足够的话,可以再进行下面一些剪枝:
一,可以进行预处理,计算反向shuffle k步后数字可能在的位置。
二,可以对于出错位置较少的情况另做处理。
我相信这样足以解出此题。

Problem E
简单的数学题。每个room对应的日照时间都是一个连续的区间。枚举并进行区间切割即可。

Problem F
此题坐标范围太大,首先要进行离散化。离散化后进行bfs即可。但算法实现上有很多的技巧。首先要清楚的认识到进行离散化得到一个网格后,哪些是边,哪些是点。我们是在边上移动还是在格子中移动?移动的费用是多少?由于穿过一条马路才会使得费用加1,这题不能直接进行bfs,而是要每次bfs得到一个费用的等价类,然后一层一层推进。可以采取的一种技巧是把坐标都乘2,把点和格子都对应成格子。还有一种好方法是把每个矩形染一种不同的颜色,bfs的时候,同色的格子就是互相可达的。
这两种方法都免去了线段的处理。当然了,如果不怕麻烦,用最直接的办法处理也是可行的。
这题也是一个很好的综合题。首先是压缩映射的一个离散化,然后进行bfs的时候还有多处难处理的细节。此题要简洁正确的实现远比想出算法困难,建议自己动手实现。

Problem G
这是本次比赛的压轴题,找了一个很困难的定理来出这个题目,本题与希尔伯特第18问题相关。虽说给了提示,但还是没有明确的可以入手的地方。比赛中几乎所有的队避开了这个题目。我没有细想这个题目,如果你有任何想法请告诉我。

Problem H
不少队伍用二分图赋权匹配解决这个问题。其实对于horizontal和vertical的情况都可以贪心,就是diagonal较为麻烦。这题只有15个点,即使匹配也不需要用经典的算法。直接进行状态空间dynamic programming即可,非常容易实现。

Problem I
每个workshop都从14点开始,所以一个room最多容纳一个workshop,从而是一个明显的二分图赋权匹配。由于有两个权,所以要先进行一个转化。
如果不是每个room只能容纳一个workshop的话,就变成了bin packing,不可能解决这么大规模的问题。

Problem J
也是简单题,枚举加上容斥原理。20 choose 10肯定小于2^20,m<=10,所以时间复杂度上可以接受。本题用位运算实现非常方便。

总结
难度上,除了A,D,G三题,其它都不算难。一支优秀的队伍应具备做出7题的实力,而能做出8题的则是世界级。考虑到现场发挥对选手的影响,做出7题已是不易。最后结果,上海交大解决D题,是唯一一支做出8题的队,从而夺冠。共有5支队做出7题。难度的梯度我个人认为不是太好。AG两题过难,几乎不太可能比赛时做出来。而又有7题较常规,所以变成了D题定胜负的局面。如果能把A和G换成与D难度相当的题目,最后想必会出现激烈的争夺。

题型上,简单题的算法略显直观,综合题也都是轻易就能拆分成若干个子问题。共有两题用到二分图赋权匹配,三题用到状态空间dp。缺少了一些技巧性强的图论题和数学题不得不说是一个遗憾。算法总体来说过于常规,缺少了对创造性的考察。ADG三题可以说需要一些创造性,可惜题目太难,即使选手有想法,在final这样的比赛中也不会贸然去试。

总体上讲是一份不错的题目,不过风格上和欧洲题目有明显的不同。上交能获得冠军是他们深厚的基本功的体现,而做出D也许要仔细的分析和一些灵感。如果能把AG两题换成难度大但是有趣的图论和数学题的话,相信会使得比赛更有意思。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: