数字三角形--动态规划

问题的提出:

  • 在数字三角形中寻找一条从顶部到底边的路径,
  • 使得路径上所经过的数字之和最大。
    如:
    {2},
    {6,9},
    {9,5,6},
    {9,8,1,9},
    {4,5,2,6,5}
    最大和为 2+9+9+9+6=35 (分治法)

常规的思路是应用分治法 找出每一层最大的项 统一相加得到最大路径
此处使用动态规划的方法。

算法思想:

  • 1.将原问题分解为子问题:原问题为求解顶层到底层路径最大数字和,分解为每一层到底层路径最大数字和,5个问题
  • 2.确定状态:使用 mstb (max_sum_to_bottom) 数组保存每一层次到底边的最大和
  • 3.确定初始态值:此处初始态为底边到底边最大值 即mstb[4]
  • 4.确定状态转移方程:mstb[i] = mstb[i + 1] + getMaxNumber(numbers[i]);

C++代码

class MaxSum
{
    //数字三角形
    //此处使用初始化的数组 避免手动初始化的麻烦
    //此处仅做演示,如果用作其他用途可改写
    int numbers[5][5] = { 
        {2}, 
        {6,9}, 
        {9,5,6}, 
        {9,8,1,9}, 
        {4,5,2,6,5} 
    };
    int mstb[5];	//max_sum_to_bottom,某一层到达底边最大的和,mstb[0]表示第一层到达底边最大和
	public:
    //找出数组最大元素
    int getMaxNumber(int* const &numbers) {
        int max = 0;
        int length = sizeof(numbers);
        for (int i = 0; i < length;i++) {
            if (max < numbers[i]) {
                max = numbers[i];
            }
        }
        return max;
    }
    //输出三角形
    void print() {
        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                if (numbers[i][j] > 0) {
                    cout << numbers[i][j] << ends;		//undo: 没有对0以及负数做考虑
                }
            }
            cout << endl;
        }
    }
    //获取从顶至底最大和
    int getMaxSum() {
        mstb[4] = getMaxNumber(numbers[5]);
        for (int i = 3; i >= 0; i--) {
            mstb[i] = mstb[i + 1] + getMaxNumber(numbers[i]);
        }
        return mstb[0];
    }
};

测试代码

class Problem1Tester{
public:
    MaxSum max_sum;

    void getMaxNumber_Test() {
        max_sum.print();
        int numbers[5] = {8,5,9,5,1};
        cout << max_sum.getMaxNumber(numbers) << endl;
    }
    void getMaxSum_Test() {
        max_sum.print();
        cout << max_sum.getMaxSum() << endl;
    }
}tester1;

参考:
http://blog.csdn.net/baidu_28312631/article/details/47418773

原文地址:https://www.cnblogs.com/liyuquan/p/7082300.html