装备强化问题是一个广泛讨论的问题,这里记录一道我看到的装备强化问题。用以记录该类问题的解决办法。本文没有使用马尔可夫链解决问题,因为我并不很擅长。本文会先用逻辑清晰但较为繁琐的思路推理,最后总结简单的通用办法。再然后利用程序统计模拟,验证结果。
问题描述:每强化一次装备需要12个道具A。初始强化等级为1级,其强化成功率和失败的惩罚如下图,请问强化到9级,平均需要多少个道具A。

强化详情
分析问题,首先强化到9级,可以拆分成从1级逐步强化到9级,最终强化到9级的期望次数等于逐级强化的期望次数之和。
首先强化到2,3,4级很简单,强化必然成功,所以强化失败的回归等级其实没有意义。因此这三次强化的期望消耗均为12。
强化到5,6级,强化概率不再是100%,但是失败后会保留原本等级,不会回退。所以可以看作独立重复实验。期望次数可以用1除以概率即可。
强化到7级,这里就值得注意了,上面的简单方法不再适用。此时,可以从数学期望的公式入手。
强化到7的成功率为70%,失败率为30%,强化失败将从6级退回到5级,而从5级再度回到6级的状态,平均需要消耗15个道具,此时再度花费12,重新进行6-7的升级强化,也就是说,每次重新回到6级,再进行一次升7的强化都平均需要花费15+12=27个道具。
下面分别介绍两种方法。首先第一种继续刚才的思路。
因此,由强化到7级的分布列,可以得到其消耗的期望公式的形式如下。
而将上式子进行整理,可以拆分成两个求和;其期望和求和的关系如下。
等差数列和等比数列的乘积,使用错位相减求解即可,求解过程繁琐,此处不详细写明,结果为。
最终,我们求得了结果。这是一种思路比较清晰的做法,求算每个随机变量对应的概率,最终使用期望公式计算,但计算过程过于繁琐,在实际工作中,也不容易在excel中创建公式。
那么接下来尝试用第二种思路,逻辑的思路。
事实上,无论是哪一次强化,行为都是可以被公式化的,即是:首先支付一次本等级强化到下一等级的费用(本题目中均为12),然后如果强化失败回退,无论是回退到几级,都一定可以求算一个从回退等级强化到当前等级的消耗期望,把这一部分看作一个整体。即每次强化失败,都要加“消耗期望”的金额。举例来说。比如6~7的升级。
首先必定支付12个道具,如果成功,则不继续;如果失败,继续2步骤。
失败一次的概率是30%,如果失败,继续支付27个道具。
如果两次失败,概率就是30%*30%,在上一步骤基础上,继续追加27个道具重新执行6-7的升级。
.....以此类推,直到强化成功,不再追加资源。
其资源计算可以用下公式表达:
直接对后面部分用等比数列的求和公式,即可得到和上面相同的结果。
而将这种计算方式推广到任意情况,只要计算好,退回等级和当前等级之间的消耗,就可以采用上方的公式,进行求算,当退回等级等于如今等级,返回状态的消耗即为0,等比数列的求和公式直接替换0.3为当前等级强化的失败几率即可。推广到了一般以后,就可以利用excel键入公式拉表解决问题。(推广过程书写繁琐,可以直接查看下面的excel公式理解。)
强化结果:

强化结果
相对位置

相对位置

单元格p4公式参考
将上面的问题,利用代码,书写循环体,统计十万次求平均值,蒙特卡洛模拟得到结果验证上面的结论。展示代码如下:
import random
import numpy as np
data={1:[1,1,12],
2:[1,2,12],
3:[1,3,12],
4:[0.9,4,12],
5:[0.8,5,12],
6:[0.7,5,12],
7:[0.6,1,12],
8:[0.5,1,12]}#创建字典,用于储存装备状态。
def intensify(data,start_cost,goal_level,start_level):
cost=start_cost
level=start_level
while level<goal_level:
temp_prob=random.random()
cost+=data[level][2]
if temp_prob<data[level][0]:
level+=1
else:
level=data[level][1]
return cost#构建函数以某等级强化到某等级所需资源
result_list=[]#创建空列表用于储存每单次强化资源需求。
for i in range(100000):#循环模拟多次,求期望值
temp=intensify(data, 0, 9, 1)
result_list.append(temp)
result=np.mean(result_list) 得到强化至9级的期望次数为:

模拟结果
与我们用公式计算得到的结果357.0159相差无几,所以上面的求算过程无误。顺便修改一下上面函数的参数,可以验证一下6~7的期望次数。

模拟6~7期望次数
与求算结果23.57143结果相差无几。
本文到此就完结了,实际工作中,如果代码能力足够的话,我还是推荐直接采用统计模拟的方式。省心省力。