[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
posted @ 2013-07-27 10:36  beautifulzzzz  阅读(830)  评论(0编辑  收藏  举报