• 数字三角形


    有一些非负数组成的三角形,第一行只有一个数,除了最下行之外每个数左下方和右下方各有一个数如下

                      1                                                                          

                 3         2

            4        10       1

       4         3         2      20

    从第一行的数开始。每行可以左下或右上走一格,直到走到最下行,把沿途经过的数全部加起来,最大数会为多少?

    (0,0)      
    (1,0) (1,1)    
    (2,0) (2,1) (2,2)  
    (3,0) (3,1) (3,2) (3,3)

     

    分析:显然n层数字三角形的走法有2^n种,于是穷举法显然不行。用d[i][j]表示从格子(i,j)出发时获得的最大效益,于是问题的解为d[0][0]的解的效益,那摩下一步有两种选择,左下走或者右下走,如果左下走那摩问题转化为求从(i+1,j)走到底层的最大效益即为d[i+1,j],如果右下方走那摩转换为从(i+1,j+1)走到底层的效益,即为d[i+1,j+1],那摩我们选择的自然是d[i+1][j]和d[i+1][j+1]中最大者,于是状态转方程为:

                                     d[i][j]=a[i][j]+max{d[i+1,j],d[i+1,j+1]};

    每一个子序列必须是最优子结构,全局最优解包含局部最优解

    直接用递归的方法计算效率非常低,原因是相同的之问题被重复计算了多次,于是选择将需要的子结构记忆性存起来,选择递推

    #include<iostream>
    using namespace std;
    int Max(int a,int b){
    return a > b ? a : b;
    }
    #define n 4
    int a[n][n];
    int d[n][n];
    int main(){
    int i, j;
    for (i = 0; i < n; i++)
    for (j = 0; j <= i; j++)
    cin >> a[i][j];
    for (i = 0; i < n; i++)
    /*边界初始化*/
    d[n - 1][i] = a[n - 1][i];
    for (i = n - 2; i >= 0; i--)
    for (j = 0; j <= i; j++)
    d[i][j] = a[i][j] + Max(d[i + 1][j], d[i + 1][j + 1]);//自低向上计算
    cout << d[0][0];
    return 0;
    }

    方法二,记忆化搜索,使用递归

    #include<iostream>
    using namespace std;
    int Max(int a,int b){
    return a > b ? a : b;
    }
    #define n 4
    int a[n][n];
    int d[n][n];
    int D(int (*a)[n], int i, int j);
    int main(){
    int i, j;
    memset(d, -1, sizeof(d));//批量赋值为-1
    for (i = 0; i < n; i++)
    for (j = 0; j <= i; j++)
    cin >> a[i][j];
    cout << D(a,0, 0) << endl;
    return 0;
    }
    int D(int (*a)[n],int i, int j){
    if (d[i][j]>0)return d[i][j];//如果d[i][j]>0说明d[i][j]已经计算过,无需再计算
    /*赋值表达式的值为左值,递归调用*/
    return d[i][j] = a[i][j] + (i == n - 1 ? 0 : Max(D(a, i + 1, j), D(a, i + 1, j + 1)));
    }

    如果已经计算过的就为非负数,于是不需要在计算,可以算到每个节点访问一次,时间复杂度为O(n^2),称为记忆法

  • 相关阅读:
    方法转换IE、Firefox、Chrome区别
    splice方法便签
    webstorm主题网址+使用方法
    从程序员到项目经理(一):没有捷径
    界面原型图绘制工具Pencil
    程序员:伤不起的三十岁
    从程序员到项目经理(三):认识项目经理
    从程序员到项目经理(二):如何胜任
    原型制作软件 Axure RP
    软件界面原型设计工具 UIDesigner
  • 原文地址:https://www.cnblogs.com/td15980891505/p/4453608.html
Copyright © 2020-2023  润新知