数字三角形问题

数字三角形问题是DP的经典入门问题

一共有三种计算方式:
直接递归计算(有一点回溯法的味道)

递推计算

记忆化搜索

其中记忆化搜索和直接递归计算非常的相似,只不过记忆化搜索将之前计算过的某些部分记录了下来,供以后使用。但是直接递归以前算过的依旧还是要算

下面贴上代码:

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
using namespace std;
const int maxn = 100;
int A[maxn][maxn];
int d[maxn][maxn];
int d1[maxn][maxn];
int n;
//递推计算
int solve1()
{
    for(int i = 1;i <= n;i++)
    {
        d[n][i] = A[n][i];
    }
    for(int i = n - 1;i >= 1;i--)
    {
        for(int j = 1;j <= i;j++)
        {
            d[i][j] = max(d[i + 1][j],d[i + 1][j + 1]) + A[i][j];
        }
    }
    return d[1][1];
}
//记忆化搜索
int solve2(int i,int j)
{
    if(d1[i][j] != -1)//在这个地方设置一个vis数组也是可以得
    {
        return d1[i][j];
    }
    if(i == n)
    {
        d1[i][j] = A[i][j];
        return d[i][j];
    }
    d1[i][j] = max(solve2(i + 1,j),solve2(i + 1,j + 1)) + A[i][j];
    return d1[i][j];
}


//完全递归计算
int solve(int i,int j)
{
    if(i == n)
    {
        return A[i][j];
    }
    else
    {
        return max(solve(i + 1,j),solve(i + 1,j + 1)) + A[i][j];
    }
}


int main()
{
    memset(d1,-1,sizeof(d1));
    n = 26;
    for(int i = 1;i <= n ; i++)
    {
        for(int j = 1; j <= i;j++)
        {
            A[i][j] = rand()%10;
        }
    }
    printf("%d\n",solve(1,1));
    printf("%lf\n",(double)clock()/CLOCKS_PER_SEC);
    printf("%d\n",solve1());
    printf("%lf\n",(double)clock()/CLOCKS_PER_SEC);
    printf("%d\n",solve2(1,1));
    printf("%lf\n",(double)clock()/CLOCKS_PER_SEC);
}

在n = 26的时候,直接递推速度已经很慢了

但是在n = 100 的时候,递推和记忆话搜索还几乎不需要时间

posted @ 2019-03-05 11:32  Toretto瑞  阅读(344)  评论(0编辑  收藏  举报