0470 Ramvok游戏
* * * *
拉格朗日计划
* * * *
Ramvok游戏

Ramvok游戏的规则如下:

用t表示游戏最多可以进行的轮数,若$t=0$,则游戏立刻终止,否则在第i轮时玩家掷一个骰子,若$i
$t$的值由玩家在游戏开始前选定,且玩家必须为此付出$ct$的点数(设初始时玩家总是有足够的点数开始游戏),其中$c$是某个给定的常数。若$c=0$,那么$t$可以选择为无穷,此时付出仍视为0。

令$R(d, c)$为给定$c$和$d$面骰、且玩家始终选择最优策略时的期望收益,例如可以验证$R(4, 0.2)=2.65$。

超级Ramvok游戏的规则则如下:

玩家不断进行Ramvok游戏,但在每次Ramvok游戏结束后都再掷出一次骰子,若所得的面上有点数就将这一面改为空白,否则若该面已经是空白了,则恢复其原来的点数。此外,在Ramvok的每一轮中,若玩家掷出空白面则需再次投掷直到掷出点数为止。当所有的面都为空白的时候,超级Ramvok游戏结束。

令$S(d, c)$为给定c和d面骰、且玩家始终选择最优策略时的期望收益,例如可以验证$S(6, 1)=208.3$。

再令$F(n)=\sum_{d=4}^n\sum_{c=0}^nS(d, c)$,求$F(20)$并四舍五入到整数。

本题难度:



解答

若$c=0$,那么显然最优策略是选择$t=\infty$并等待最大点数出现。若$c>0$,则选择$t$时的期望收益$E_t$可以递归计算:$E_0=0$,而 $$E_t=\frac{1}{d}\sum_{i=1}^d\max(r_i, E_{t-1}),$$ 其中$r_i$是骰子第$i$面上的点数。这是因为掷出点数后只需比较所得点数和进行$t-1$轮的期望收益就可以决定是否需要继续。

递推求出解即得结果$147668794$。

注:因使用numpy求矩阵逆,以下代码为Python 3。

from numpy import linalg

d=20

def E(a,c):
    if len(a)==0:
        return 0
    if c<=0:
        return max(a)
    x=sum(a)/len(a)
    y=x-c
    z=0
    t=1
    while y>z:
        t+=1
        z=y
        x=sum(max(k,x) for k in a)/len(a)
        y=x-c*t
    return z


S=[[[]], [[1],[2],[3]], [[1,2],[2,3],[1,3]], [[1,2,3]]]+[[] for k in range(d-3)]
P=[[sum(E(j,k) for j in S[i]) for i in range(4)]+[0]*(d-3) for k in range(d+1)]

res=0
for n in range(4,d+1):
    mat=[[1 if i==j else 0 for j in range(n)] for i in range(n)]
    for i in range(1,n):
        mat[i][i-1]=(i-n)/n
    for i in range(n-1):
      mat[i][i+1]=-(i+2)/n
    for j in range(n-1,-1,-1):
        for k in S[j]:
            S[j+1].append(k+[n])
            for i in range(d+1):
                P[i][j+1]+=E(k+[n],i)
    res+=sum(linalg.solve(mat,P[c][1:n+1])[-1] for c in range(n))
    print(n,res)

print(round(res))