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

  这是第三题,还没有搞定,等搞定了在补上。

转载于:https://www.cnblogs.com/Frandy/archive/2012/04/29/google_code_jam_2012_round1a_python.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值