动态规划 - 数字三角形

数字三角形

有正实数构成的数字三角形排列形式如图所示,第一行的数为\(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}\)中某个数的一条路径,并使得该路径上的数之和达到最大。
image
image
定义数组元素
把当前的位置\((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]\)时的路径选择,即

\[k[i,j] = \left\{ \begin{array}{lr} j & 若F[i-1,j]>F[i-1,j-1]\\ j-1 & 否则 \end{array} \right. \]

猜你喜欢

转载自www.cnblogs.com/HIIM/p/12722862.html