两人交替从数组左右两端拿数,求谁会赢

'''
Descripttion: 有一个由正整数组成数组,每次只能拿最左边的数或最右边的数,
    两个人交替拿数,求先手的和后手的谁会赢
Author: lishaogang
version: 
Date: 2021-12-07 08:38:14
LastEditors: lishaogang
LastEditTime: 2021-12-07 09:11:06
'''


def numberGet(arr):
    def f(arr, l, r):
        '''
        先手的操作'''
        if l == r:
            return arr[l]
        return max(
            arr[l]+s(arr, l+1, r),
            arr[r]+s(arr, l, r-1)
        )

    def s(arr, l, r):
        '''
        后手的操作'''
        if l == r:
            return 0
        # 因为是后手,所以先手会先选择他算出来的值会比较大的数,剩给后手的相比较小的情况(故用min)
        # 后手只能从剩下的这些数中作为先手去选择对它最有利的选择(故使用f函数)。
        return min(
            f(arr, l+1, r),
            f(arr, l, r-1)
        )
    return max(f(arr, 0, len(arr)-1), s(arr, 0, len(arr)-1))


def numberGet2(arr):
    '''
    使用动态规划来解决这个问题'''
    l = len(arr)
    f = [[-1]*l for i in range(l)]  # f表示先手拿到的最好结果,
    # 如第i行第j列的值表示从第i个数开始到第j个数,作为先手能够拿到的最高的分

    s = [[-1]*l for i in range(l)]  # s表示后手拿到的最后的结果,
    # 如第i行第j列的值表示的是从第i个数开始到第j个数,作为后手能够拿到的最高分

    for i in range(l):
        f[i][i] = arr[i]
        s[i][i] = 0

    for j in range(1, l):
        x = 0
        y = j
        while y < l:
            f[x][y] = max(
                arr[x]+s[x+1][y],
                arr[y]+s[x][y-1]
            )
            s[x][y] = min(
                f[x+1][y],
                f[x][y-1]
            )
            x += 1
            y += 1
    return "先手赢" if f[0][l-1]>s[0][l-1] else "后手赢" #这样求到的是谁能赢
    # return max(f[0][l-1], s[0][l-1])    #这样求到的是两人中能够拿到的最高分


if __name__ == "__main__":
    arr = [1, 100, 30, 50, 20]
    # res = numberGet(arr)
    res = numberGet2(arr)
    print(res)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值