动态规划&数字三角形

数字三角形

  • 题目:
    有一个由非负整数组成的三角形,第一行只有一个数,除了最下行之外的每个数正下方和右下方各有一个数,只能往正下或者往右走一步,从上到下加起来最大的数是多少?

    数字三角形
  • 分析:
    求最优的问题,考虑使用动态规划。动态规划可以用填表法可以更好理解其状态转移方程,一般可以维护两个表:value[][]表用以记录子问题的最优解,status[][]表用以记录状态(有些问题需要记录填表的路径)。这里使用a[i][j]存储这个数字三角形。使用F[i][j]记录value[][]。F[i][j]表示从[0][0]出发到达[i][j]所能得到的最大值。

  • 状态转移方程:

    F[i][j]=a[i][j]+max{F[i-1][j-1],F[i-1][j]}


    • 解释:理解状态转移方程很重要。在求F[i][j]的时候,路径只能是从左上方或者正上方来,即依赖值F[i-1][j-1],F[i-1][j]。此时必然要求F[i-1][j-1]和F[i-1][j]是从(0,0)点到(i-1,j-1)和(i-1,j)所能获得的最大值。
    • 用填表法模拟动态规划的过程:
      • 对F表,先填容易填的,确定的作为对F表的初始化:
        初始化F表
        由于路径只能向下或向右,因此表中填好的数据没有别的选择,只能取如图数值。


      • 对于剩下的3个未填空格,取F[2][1]作为例子。路径只能从F[1][0]或者F[1][1]来。显然4>3,因此我们选择F[1][0]。而F[1][0]已经是从(0,0)到(1,0)所能得到的最大值了。
        填F表
        剩下的填法一样。


  • 代码示例:
#include<iostream>
#include<cstring>
using namespace std;
const int maxn = 100;
int a[maxn][maxn];
int value[maxn][maxn];
int status[maxn][maxn];

#define max(x,y) (x>y?x:y)

int main(){
    int n;  //输入数字三角形的层数
    while(cin>>n,n!=0){
        memset(value,-1,sizeof(value));
        for(int i=0;i<n;i++){
            for(int j=0;j<=i;j++){
                cin>>a[i][j];
            }
        }


        value[0][0] = a[0][0];

        for(int i=1;i<n;i++){
            for(int j=0;j<n;j++){
                if(j==0)    value[i][j] = value[i-1][j];
                else{
                    value[i][j] = max(value[i-1][j-1],value[i-1][j]);
                }
            }
        }

        for(int i=1;i<n;i++){
            cout<<endl;
            for(int j=0;j<n;j++){
                cout<<value[i][j];
            }

        }
    }
}

猜你喜欢

转载自blog.csdn.net/l_apple8/article/details/53166815