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个字母的映射关系,那么如果示例里面有剩下的映射关系,问题就解决了。测试了一下,示例确实给出了剩下的映射关系,那么就这样解决了。

  下面给出代码,

View Code
#!/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的个数。

  代码如下,

View Code
#!/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,移一位和移三位的数是一样的,但是只能算作一对。

  于是,得到下面的代码,

View Code
#!/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, 而对出现过的数是不需要在进行数对计数的。

  所以有了下面的代码,

View Code
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

  这道题还没搞定,也还没看参考答案。等有斗志了在研究吧。

posted @ 2012-05-10 23:29  Frandy.CH  阅读(405)  评论(0编辑  收藏  举报