Google Code Jam 2012 Round 1A
昨天Google Code Jam 2012 Round 1A。由于没有注意到它只进行两个半小时,而不是从你开始做开始计时,直接错过了参加比赛。
后来看了一下题目,新题目还是比较有意思的,下面就给出各题的参考和实现。
A. Password Problem
第一道题,跟概率有些关系。先理解一下题目意思。
一个人在输入一个很长的密码,输到一半时觉得前面可能有地方错了,那么他有三种选择,
1、继续输入,提交,如果没有错,ok。如果有错误,那么重新输入,这一次一定不会输错;
2、按退格键若干格,然后完成输入并提交。新输入的部分是不会出错的。如果错误被空格键清除,那么提交通过,否则需要重新输入,跟1中的操作类似;
3、放弃这次输入,然后重新输入并提交。重新输入也不会出错。
如果输入一个密码中的字符,或者敲一次回车键进行提交,按一次退格键,或者选择放弃,都算做一次键盘敲击。题目给出已经输入的字符数和密码长度,和已经输入部分的字符是正确的概率。要求计算出这些操作中的最小期望值。
下面是解题过程,
已经输入字符数A和密码长度B,已经输入部分字符正确的概率p[1..A]。
选择操作3,期望e3=B+2;
选择操作1,那么期望就是e1=输入部分全部正确的概率*剩余的输入次数(B-A+1) + 需要重新输入的概率 * (B-A+1+B+1);
选择操作2,得根据退格键的次数分A种情况,退格键k次的时候,那么输入有效的概率是前A-k个字符正确,第A-k+1个字符不正确时,剩余输入次数为B-A+1+2k,否则剩余次数为B-A+1+2k+B+1。第一种情况,可以看作是k=0的结果。
所以核心代码如下:
def solveN(A,T,p): res = T+2 s = 1 for i in xrange(A): s *= p[i] e = (T-i) + (A-i-1) + (T+1) * (1-s) res = min(res,e) return res
B. Kindom Push
Kindom Push是题目中用到的素材,Ryan在玩一个等级过关游戏,闯关需要一定数量的金币star,每关有两个闯关方法,一是直接闯过2-rating得到两个金币star,另一种是先闯过1-rating,可以得到一个金币star。如果某一关的1-rating已经闯过,那么再闯过2-rating就只能得到一个金币star。然后题目会给定关数和每一关的1-rating和2-rating分别需要的金币数,需要得到最少多少次可以完成所有关卡,或者不可能闯关成功。
例如,
有3关,每一关的两种情况需要的金币数(0,1),(0,2),(0,5),最开始Ryan的金币数为0,可以完成level 1的1-rating或者level 2的1-rating或者level 3的1-rating,得到金币1,接下来可以完成level 1的2-rating,如果第一次完成的是level 1的1-rating,那么现在只有2金币,如果完成的是level 2或者level 3的1-rating,那么现在完成level 1的2-rating后有3金币,接下来可以完成level2的2-rating。虽然此时都可以完成level 2的2-rating,但是如果之前用的是level 2的1-rating,那么现在最多就只有4金币,然而如果最开始用的是level 3的1-rating,那么现在就有5金币,可以完成level 3的2-rating,完成闯关。
所以,可以先按2-rating从小到大排序,因为只有2-rating完成,才算所有闯关完成,那么2-rating是必须完成的。如果star能够完成某个level的2-rating,那么就直接完成。如果不能,则需要先完成某些level的1-rating。关键问题就是,如果有多个level的1-rating都可以选择,选择哪一个呢?首先如果该level的2-rating已经完成,那肯定是不用选的,因为完成它不能增加金币数。如果有多个level的2-rating没有完成,那么选2-rating 要求最高的level的1-rating。就像例子里面,选择2-rating=5的level的1-rating完成。因为这样可以避免2-rating 较低的失去获得2-rating的机会。
那么核心代码如下:
def solveN(N,data): data.sort(); # print data rec = [[0,0] for i in xrange(N)] star = 0 res = "0" cnt = 0 flag = 1 i = 0 while(i<N): if star>=data[i][0]: if rec[i][1]==1: # print "1-2-rating level",i star += 1 else: # print "2-rating level",i star += 2 rec[i][0] = 1 i += 1 else: tj = -1 tm = 0 for j in xrange(i,N): if rec[j][1]==0 and rec[j][0]!=1: if star>=data[j][1]: if data[j][0]>=tm: tm = data[j][0] tj = j if tj==-1: flag = 0 break rec[tj][1] = 1 star += 1 # print "1-rating level",tj cnt += 1 # print rec if flag==0: res = "Too Bad" else: cnt += N res = str(cnt) return res
因为每个level的2-rating必须完成的,所以对2-rating排序后,直接挨个完成,不能完成的时候,就从后面没有完成的level中选择1-rating可以完成的所有level中2-rating最高的level,完成1-rating。因为用到sort函数,上面data的第一列是2-rating,第二列才是1-rating。
C. Cruise Control
这是第三题,还没有搞定,等搞定了在补上。