欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

排成一条线的纸牌博弈问题

发布时间:2025/4/5 编程问答 34 豆豆
生活随笔 收集整理的这篇文章主要介绍了 排成一条线的纸牌博弈问题 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

题目】

  给定一个整型数组arr,代表数值不同的纸牌排成一条线。玩家A和玩家B依次拿走每张纸牌,规定玩家A先拿,玩家B后拿,但是每个玩家每次只能拿走最左边或者最右边的一张牌,最后所拿牌累加和最大的玩家获胜,玩家A和玩家B都绝顶聪明。请返回最后获胜者的分数。

【举例】

  arr = [1, 2, 100, 4] 
  玩家A先拿1,玩家B拿4,玩家A再拿100,玩家B再拿2,游戏结束,玩家A获胜,分数为101。

【基本思路】

  首先分析暴力递归的方法。定义递归函数f(i, j)表示如果arr[i…j]这个排列上的纸牌被绝顶聪明的人先拿,最终会获得什么分数。定义递归函数s(i, j),表示如果arr[i…j]这个排列上的纸牌被绝顶聪明的人后拿,最终能获得什么分数。

首先分析f(i, j),具体过程如下:

如果i == j,表示此时只有一张牌,当然会被先拿牌的人拿走,所以返回arr[i]即可。

如果i != j,那么此时有两种选择,一种是先拿arr[i],一种是先拿arr[j]。如果先拿走arr[i],那么对于剩下的arr[i+1…j],玩家成了后拿牌的人,所以他能获得的分数为arr[i] + s(i+1, j);同理如果先拿arr[j],那么他能获得的分数为arr[j] + s(i, j-1)。因为玩家是决定聪明的人,所以他会选择两个决策中最优的,即max(arr[i] + s(i+1, j), arr[j] + s(i, j-1))。

接下来分析s(i, j),具体过程如下:

如果i == j,表明此时只有一张牌,对于后拿牌的人来说,他肯定拿不上,说以返回 0。

如果i != j,那么此时玩家的拿牌方式其实受到对手的影响,如果对手选择的是arr[i]那么给玩家留下的就是arr[i+1…j],对于排列arr[i+1…j]玩家成了先拿牌的人,所以他能得到的分数为f(i+1, j)。同理,如果对手选择的是arr[j]那么给玩家留下的就是arr[i…j-1],对于排列arr[i…j-1]玩家成了先拿牌的人,所以他能得到的分数为f(i, j-1)。因为对手也是绝顶聪明的,所以留给玩家的一定是最坏的情况,所以玩家只能选择两个决策中最差的,即max(f(i+1, j), f(i, j-1))
 

def win1(L):"""暴力递归"""if L == None or len(L) == 0:return 0return max(f(L,0,len(L)-1),s(L,0,len(L)-1))def f(L,i,j):if i==j:return L[i]return max(L[i]+f(L,i+1,j),L[j] + f(L,i,j-1))def s(L,i,j):if i==j:return 0return min(f(L,i+1,j),f(L,i,j+1))def win2(L):if L == None or len(L) == 0:return 0f = [[0]*len(L)] * len(L)s = [[0]*len(L)] * len(L)for j in range(1,len(L)):f[j][j] = L[j]for i in range(j-1,0,-1):f[i][j] = max(L[i]+s[i+1][j],L[j]+s[i][j-1])s[i][j] = min(f[i+1][j],f[i][j-1])return max(f[0][len(L)-1],s[0][len(L)-1])

 

总结

以上是生活随笔为你收集整理的排成一条线的纸牌博弈问题的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。