后效性 顾名思义,就是指 到当前A状态的决策会限制今后(包含A状态的)状态B能够做的决策
举个例子:
数塔问题变种
同样是数塔,在向下走的规则上有一定改动——允许且仅允许一次从该层的某位置转移到下一层的任意位置,其他地方的规则不变
我们在尝试写DP方程时遇到了问题
原数塔问题是d[i][j]=max{d[i-1][j],d[i-1][j-1]}+num[i][j];
但是。。规则说允许一次从该层的某位置转移到下一层的任意位置,如果d[i-1][j]以及之前的决策中已经使用过了任意转移的机会,那么这次转移就不能再使用了(d[i-1][j-1]是同样的)。反过来,如果还没有使用机会,那么这次转移就可以考虑一下是否使用。。问题就在这儿!我们单单从d[i-1][j]是看不出它到底用没用机会。如果使用原方程,就会出现错误,这就是后效性。 d[i-1][j]时的决策影响到了d[i][j]的某决策是否可以考虑。
那么,解决办法是什么呢?
1.记录决策:
记录以前作的决策,然后就能够知道当前状态可以考虑的决策数
很遗憾,这个方法是错的。。
仔细想想就会明白,这个不符合最优子结构了
等于说是“逼着”后面状态去迁就前面的状态
实质上没有取消后效性。(仅仅明确了当前受限制后的决策是什么。。但是后效性没有任何消除)
2.增加维数
既然我们不能“逼着”后面状态作抉择,那么我们就应该给它选择的余地。
其实后效性来源就是对状态的描述不够细致到位,因此扩大维数即可
用d[i][j][0]表示从(i,j)处走下去且路径上都不使用任意转移
d[i][j][1]表示从(i,j)处走下去且路径上会存在使用任意转移
那么显然 d[i][j][0]转移与原方程一致
d[i][j][1]=max{d[i-1][j][1]/*把机会让给从d[i-1][j]*/,d[i-1][j-1][1] /*把机会让给从d[i-1][j-1]*/,S /*使用这次机会*/}
S=所有d[i-1][x]和