[ACM_动态规划] 数字三角形(数塔)_递推_记忆化搜索

1、直接用递归函数计算状态转移方程,效率十分低下,可以考虑用递推方法,其实就是 “正着推导,逆着计算”
#include<iostream>

#include<algorithm>

using namespace std;

#define maxn 1000+5

int n;

int a[maxn][maxn];

int d[maxn][maxn];

int main(){

    

    for(;cin>>n && n;){

        memset(d,0,sizeof(d));

        int i,j;



        for(i=1;i<=n;i++){     //输入

            for(j=1;j<=i;j++){

                cin>>a[i][j];

            }

        }



        for(j=1;j<=n;j++){     //计算最底层d[][]值

            d[n][j]=a[n][j];

        }



        for(i=n-1;i>=1;i--){   //从下向上计算d[][]值

            for(j=1;j<=i;j++){

                d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]);

            }

        }

        cout<<d[1][1]<<'\n';

    }

}
View Code
2、记忆化搜索虽然也是递归,但同时把计算结果保存在d[][]中,可以保证每个节点只访问一次(不必事先确定各状态计算顺序,但需要记录每个状态是否计算过,本题把d[][]初始为-1,>=0则算过。
#include<iostream>

#include<algorithm>

using namespace std;

#define maxn 1000+5

int n;

int a[maxn][maxn];

int d[maxn][maxn];

int D(int i,int j){

    if(d[i][j]>=0)return d[i][j];                    

    return d[i][j]=a[i][j]+(i==n ? 0 : max(D(i+1,j),D(i+1,j+1)));    //记忆化搜索要保存每次计算结果

}

int main(){

    

    for(;cin>>n && n;){

        memset(d,-1,sizeof(d));             //初始化为-1,也是为记忆化搜索做的标记,当>=0时直接返回d[][];

        int i,j;



        for(i=1;i<=n;i++){

            for(j=1;j<=i;j++){

                cin>>a[i][j];

            }

        }

        cout<<D(1,1)<<'\n';

    }

}
View Code

你可能感兴趣的:(动态规划)