Google Code Jam 2012 Qualification Round
Code Jam的Round 1已经结束了,水平太菜,已经被淘汰了。开始整理做过的题。就从Qualification Round开始吧。http://code.google.com/codejam/contest/1460488/dashboard#s=p0
Problem A. Speaking in Tongues
这道题比较简单,题目大概意思就是一种方言,也是使用英语的26个字母,但与正常英语里面的26个字母有一个固定的映射关系,题目要求使用这种映射关系,把给定的语句翻译成另一种语句。
需要注意的是,题目是出了示例,而且有提示的3个字母的映射关系,那么如果示例里面有剩下的映射关系,问题就解决了。测试了一下,示例确实给出了剩下的映射关系,那么就这样解决了。
下面给出代码,
#!/usr/bin/python #Filename:Tongues.py import sys inname = "input.txt" inref = "inputref.txt" inres = "inputres.txt" outname = "output.txt" if len(sys.argv)>1: inname = sys.argv[1] outname = inname.rstrip(".in") outname = outname + ".out" fin = open(inname,"r") finref = open(inref,"r") finres = open(inres,"r") fout = open(outname,"w") refNum = int(finref.readline().rstrip("\n")) ori = [] res = [] ton = dict() for i in xrange(refNum): line = finref.readline().rstrip("\n") lineres = finres.readline().rstrip("\n") for j in xrange(len(line)): ton[line[j]]=lineres[j] ton["z"]="q" ton["q"]="z" #print len(ton) #print ton.keys() #print ton.values() testCaseNum = int(fin.readline().rstrip("\n")) for i in xrange(testCaseNum): line = fin.readline().rstrip("\n") answer = "Case #%d: " %(i+1) an = "" for j in line: an += ton[j] answer += an + "\n" fout.write(answer) fin.close() finres.close() fout.close()
Problem B. Dancing With the Googlers
这道题也还好,题目的意思是,三位评委给参加活动跳舞的选手打分,三位评委的分数不会相差超过2,并且如果相差2则会认为分数是比较奇怪的。现在给出些选手的总得分,和奇怪得分的个数,问有多少选手可以有至少为p的得分。
如果一个选手在没有奇怪得分的情况下,最好的得分已经大于等于p,那么可以认为它不是奇怪的。如果它在没有奇怪的得分的情况下分数都小于p,而在奇怪的得分的情况下有分数大于p,并且已经认定的奇怪的个数还没有达到给定的个数,那么就认为它的得分是奇怪的。
因为三个分数不会相差超过2,如果最低的得分是a,那么就可能是a,a+1,a+2的组合了。而给定的分数总合是s,就可以算出在得分是奇怪的和不是奇怪的情况下的得分。然后根据上面的分析,统计得分可以大于等于p的个数。
代码如下,
#!/usr/bin/python #Filename:Dancing.py import sys def solveN(T,S,p,line): line.sort() line.reverse() cnt = 0 scnt = 0 for ti in line: if ti%3==0: a = ti/3 if a>=p: cnt += 1 elif scnt<S: a = (ti-3)/3 if a>=0 and a<=10: scnt += 1 if a+2>=p: cnt += 1 elif ti%3==1: a = (ti-1)/3 if a+1>=p: cnt += 1 elif scnt<S: a = (ti-4)/3 if a>=0 and a<=10: scnt += 1 if a+2>=p: cnt += 1 elif ti%3==2: a = (ti-2)/3 if a+1>=p: cnt += 1 elif scnt<S: a = (ti-2)/3 if a>=0 and a<=10: scnt += 1 if a+2>=p: cnt += 1 return cnt inname = "input.txt" outname = "output.txt" if len(sys.argv)>1: inname = sys.argv[1] outname = inname.rstrip(".in") outname = outname + ".out" fin = open(inname,"r") fout = open(outname,"w") line = fin.readline().rstrip("\n") testCaseNum = int(line) for caseNum in xrange(1,testCaseNum+1): data = [int(val) for val in fin.readline().rstrip("\n").split()] T = data[0] S = data[1] p = data[2] ti = data[3:] an = solveN(T,S,p,ti) answer = "Case #%d: %d\n" %(caseNum,an) fout.write(answer) fin.close() fout.close()
Problem C. Recycled Numbers
这道题在一开始做的时候是做出来的,只是程序的效率比较低,small case可以顺利的跑出来,large case跑起来比较慢。所以又做了一些改进。
先看看题。两个数(A,B)构成一个数对,如果B是由A通过循环移位得到,并且A<B。如(12345,23451)就是一个数对。给定一个范围,要求得到这个范围内的数对的个数。范围的起始和终止的两个数的位数一样。
比较直接的算法就是遍历这个范围,将数A转化为字符串,然后移位,再将移位得到的字符串转化为整数,判断是否满足条件,在给定范围内并且比A大,则计数加1. 需要注意的是,如果只是这样判断会出现重复的情况。比如121212,移一位和移三位的数是一样的,但是只能算作一对。
于是,得到下面的代码,
#!/usr/bin/python #Filename:RecycledNumber.py import sys def getLen(A): l = 0 while(A>0): A = A/10 l = l + 1 return l def solveN(A,B): cnt = 0 l = getLen(A) for x in range(A,B+1): sx = "%d" %(x) trec = dict() for i in xrange(l): sx = sx[l-1]+sx[0:l-1] v = int(sx) if v>x and v<B+1: if sx not in trec: trec[sx]=v # print x,sx cnt += 1 return cnt inname = "input.txt" outname = "output.txt" if len(sys.argv)>1: inname = sys.argv[1] outname = inname.rstrip(".in") outname = outname + ".out" fin = open(inname,"r") fout = open(outname,"w") testCaseNum = int(fin.readline().rstrip("\n")) for caseNum in xrange(1,testCaseNum+1): (A,B) = [int(val) for val in fin.readline().rstrip("\n").split()] print "case",caseNum cnt=solveN(A,B) answer = "Case #%d: %d\n" %(caseNum,cnt) fout.write(answer) fin.close() fout.close()
这个在测试large case的时候速度比较慢,在考虑这个问题,如果数A经过移位,可以得到m个在给定范围的不重复的数,那么这些数能够组成的数对是C(_m)(^2)=m*(m-1)/2, 而对出现过的数是不需要在进行数对计数的。
所以有了下面的代码,
def getLenm(A): sx = "%d" %(A) return len(sx) def solveNm(A,B): total = 0 l = getLenm(A) rec = [0 for i in range(A,B+1)] for x in range(A,B+1): if rec[x-A]!=1: rec[x-A] = 1 cnt = 0 sx = "%d" %(x) for i in xrange(l): sx = sx[l-1]+sx[0:l-1] v = int(sx) if v>x and v<B+1: if rec[sx-A]==0: rec[sx-A]==1 # print x,sx cnt += 1 total += cnt*(cnt-1)/2 return total
Problem D. Hall of Mirrors
这道题还没搞定,也还没看参考答案。等有斗志了在研究吧。