动态规划 - 数字三角形
数字三角形
有正实数构成的数字三角形排列形式如图所示,第一行的数为\(a_{11}\);第二行的数从左到右依次为\(a_{21}\),\(a_{22}\);...第n行的数为\(a_{n1}\),\(a_{n2}\),...,\(a_{nn}\)。从\(a_{11}\)开始,每一行的数\(a_{ij}\)只有两条边可以分别通向下一行的两个数\(a_{(i+1)j}\)和\(a_{(i+1)(j+1)}\)。请设计一个算法,计算出从\(a_{11}\)通到\(a_{n1}\),\(a_{n2}\),...,\(a_{nn}\)中某个数的一条路径,并使得该路径上的数之和达到最大。
定义数组元素
把当前的位置\((i,j)\)看成一个状态,然后定义状态\((i,j)\)的标记函数\(F(i,j)\)为从格子\((i,j)\)出发时能得到的最大和(包括\(F(i,j)\)本身的值)
定义状态转移方程
接下来,看不同状态之间是如何转移的。
从\((i,j)\)出发,有2种选择,去\((i+1,j)\)或\((i+1,j+1)\)。
为了满足题目要求,我们选择\(F(i+1,j)\)和\(F(i+1,j+1)\)中较大的一个。
所以得到了状态转移方程
\(F(i,j)=a(i,j)+max{F(i+1,j),F(i+1,j+1)}\)
所以如果从第一个位置\((1,1)\)开始一直依靠这个方程取max向下走的话,就会得到最好情况。满足优化原则,这个性质称为最优子结构。
找出初值,最小子问题
最左边:\(F[i,1]=F[i-1,1]+a_{i1}\) \(i=2,3,...,n\)
最右边:\(F[i,i]=F[i-1,i-1]+a_{ii}\) \(i=2,3,...,n\)
\(F[1,1]=a_{11}\)
问题的最优路径的和是\(max\){\(F[n,j]|j=1,2,...,n\)}
这个递推算法中,\(i\)是逆序枚举的。
int i,j
for(j=1;j<=n;j++)
F[n,j]=a[n,j];
for(i=n-1;i>=1;i--)
for(j=1;j<=i;j++)
F[i,j]=a[i,j]+max{F[i+1,j],F[i+1,j+1]};
所以算法的时间复杂度是\(O(n^2)\)
现在得到了路径的最大值,要得到该路径,需设立标记函数。
定义标记函数\(k[i,j]\),记录得到最优\(F[i,j]\)时的路径选择,即