阿里巴巴2018校招编程测试题

题目描述

说实话第一眼看到这道题我感觉像是博弈论。30分钟的时间没有做出来,只能骗点分,证明我是会写java的···
还是说正题吧···题目是这样的,A、B是两个无聊的人,他们决定玩个游戏:现在有一个非负整数组成的数组,A和B轮流从数组中取出一个数,且只能从数组的两端取,每个人都以获得取到数之和最大的原则取数(这个原则很重要)。在数组被俩人消耗空之后,每个人计算取到的所有数字的和Sa和Sb,如果Sa >= Sb则A获胜,否则B获胜。
输入:n行,每行一个数组中的数
输出:如果A获胜,输出true,如果B获胜,输出false

解决思路

测试的时候一直按照时间顺序从游戏开始想,结果既没有猜到开头也没有猜到结尾。心情一直很郁闷。洗完澡终于开窍了。要自底向上地计算。
首先获取的数字之和最大的原则告诉我们其实A或B都只用考虑自己就好。
1. 考虑只剩一个数的情况:该取这个数的人一定会取,这样才符合原则,记录此时每种剩一个数的情况可以获得的收益。
2. 考虑剩两个数的情况:此时该取数的人一定取两个之间较大的数,这样他的情况才能更好,符合原则,计算出每种剩两个数情况下的收益。
3. 考虑剩三个数的情况:由于只能从两边取数,且俩人的选择会符合原则,故此时取数的人会考虑取左端和右端哪个数会获得更大的收益。由于剩余2个数的情况都已被计算过,对于任何剩余的三个数,可以计算取左端的数+取完剩下两个数的收益(之前计算过)和取右端的数+取完剩下两个数的收益哪一种收益更大。
4. 剩下的情况与剩三个数时类似。
5. 在整个数组被计算完毕后,会得到A和B的收益Sa和Sb,对比一下得出结果。

代码实现

使用一个三维数组answer[p][r][h],其中p为0代表A,p为1代表B。r表示正在计算数组剩余长度为r时的情况。h代表剩余数组开始的下标。
下面上代码,虽然题目不知道为什么只能用java,不过现在我用python写。。

import sys
array = [0]
n = 0
# read data in
for line in sys.stdin:
    if line == '' or line == None:
        break
    array.append(int(line))
    n += 1
# init array
answer = [[([0] * (n + 2)) for i in range(n + 2)] for j in range(2)]
# people tells who will take a number now. 0 mains A while 1 main B,
people = 1 - (n % 2)
# init answer
answer = [[([0] * (n + 2)) for i in range(n + 2)] for j in range(2)]
for head in range(1, n + 1):
    answer[people][1][head] = array[head]
people = 1 - people
# dp
for remain in range(2, n + 1):
    # remain mains the length of array remain.
    for head in range(1, n + 1):
        tail = head + remain - 1
        if tail > n:
            break
        take_tail = answer[people][remain - 1][head] + array[tail]
        take_head = answer[people][remain - 1][head + 1] + array[head]
        if take_tail < take_head:
            answer[people][remain][head] = take_head
            answer[1 - people][remain][head] = answer[1 - people][remain - 1][head + 1]
        else:
            answer[people][remain][head] = take_tail
            answer[1 - people][remain][head] = answer[1 - people][remain - 1][head]
    people = 1 - people
print answer
Sa = answer[0][n][1]
Sb = answer[1][n][1]
is_win_a = Sa >= Sb
print "Sa: ", Sa, " Sb:", Sb
print is_win_a

只是测试了自己想的简单数据,如有错误敬请指正。
如需转载请注明出处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值