ACM-GOOGLE CODE JAM 2011 Qualification Round 2011(总结)

来源:互联网 发布:编程思想知乎 编辑:程序博客网 时间:2024/06/05 19:12

 

    上周末,我分别参加了CODE JAM的资格赛和北大的PKU比赛,正规的ACM比赛都是我第一次参加,中间也经历了很多的问题和磨难,打算分几次来写写自己的心得吧。

    CODE JAM比赛是在线的比赛,必须提交测试数据集的运行结果和源代码。测试数据集分两种,一种small数据集,一种是large数据集。

    第一题:http://code.google.com/codejam/contest/dashboard?c=975485#

    题目大意是,A、B两个机器人在长廊中协作完成一个指定系列顺序的任务,机器人每移动一格需要一秒,按下一个按钮也需要一秒,必须严格按照指定系列完成任务,问最短完成的时间是多少?

    还是比较简单的吧,可以声明两个数组atime 和 btime 分别代表A、B完成下一个任务时的时间,则可以得到这样一个结论,atime[afinal] = max( atime[alast] + amove , btime[bfinal]) + 1;代表意思是机器人A完成最新任务的时间为机器人A上一次的时间加上移动到当前任务位置的时间,或者是A移动到当前任务位置以后等待B完成最新任务以后的时间,加上执行任务的时间。同样道理btime[bfinal] = max(btime[blast] + bmove, atime[afinal]) +1;

   代码如下:

 

    第二题:http://code.google.com/codejam/contest/dashboard?c=975485#s=p1

    题目大意是,一种游戏,有8个原字母,不断的添加字母,如果两个字母出现在组合逻辑中,则合并成新的字母,如果不能合并,则判断字母是否出现在排斥队列中,如果是的话,则消除整个队列(这个很重要,我第一次理解成了删除两个字母之间的所有字母)。

    我的做法是建立两个二维数组,combine[i][j] = combine[j][i] = NEWCHA,表示i,j字母可以融合成新的字母,opp[i][j] = opp[j][i] = 1表示字母i到j互相排斥。则读取一个系列的时候,先判断合并,再判断是否可以消除。题目理解对了,就相对比较简单了,复杂的数据量也没有问题。

    代码如下:

 

    第三题:http://code.google.com/codejam/contest/dashboard?c=975485#s=p2

    题目大意是:两个儿子在分糖果,然后小儿子比较笨,只会用异或的办法求和,只要小儿子觉得两边的糖果相等,就不会哭。然后要求大儿子在不把小儿子弄哭的情况下,分糖果,并且保证自己的糖果序号和最大。

    第一次看到这道题的时候,由于小数据量不大,2 ≤ N ≤ 15.因此我使用的方法是采用0-1遍历的方法,0代表不取,1代表取。遍历出所有的情况,最后进行判断。

   代码如下:

 

    但是对于大数据量来说,复杂度为2^n,明显过不了。因此,但是分析一下,假设原系列为A1, A2,A3,……An。那么小儿子觉得相等的情况为Ai ^ Aj ^ Ak ^ …… = Ax ^ Ay ^ Az ^ ……。那么也就是说,如果糖果是可分的话,A1 ^ A2 ^ A3 ……= 0,那么两边同时异或最小的数 A1^A2 ^ A3^……^An = Amin,因此,如果整个异或为0,则只要所有数求和减去最小的数,就是结果了,代码如下:

 

    最后一题比较复杂,下回单独说吧。