动态规划问题小结

动态规划(Dynamic Progamming,DP)是一种用来解决一类最优化问题的算法思想

简单来说

动态规划将一个复杂的问题分解成若干个子问题

通过子问题的最优解来得到原问题的最优解

tips:动态规划如何记录子问题的解

来避免下次遇到相同的子问题时的重复计算

以斐波那契数列代码为例

有很多重复计算的过程

为避免重复计算

开一个一维数组dp

用以保存已经计算过的结果

其中dp[n]记录F(n)的结果

并用dp[n]=-1表示F(n)当前还没有被计算过

int dp[maxn];
int F(int n)
{
    if(n==0||n==1)
        return 1;//递归边界
    if(dp[n]!=-1)
        return dp[n];//已经计算过,直接返回结果,不用重复计算
    else
    {
        dp[n]=F(n-1)+F(n-2);//计算F(n),并保存至dp(n)
        return dp[n];
    }
}

经典数塔问题:

dp[i][j]表示从第i行第j个数字出发的到达最底层的所有路径中的最大值

【分析】

如果要求出dp[i][j],一定要先求出它的两个子问题

从位置dp(i+1,j)到达最底层的最大和dp[i+i][j]和

从位置dp(i+1,j+1)到达最底层的最大和dp(i+1,j+1)

进行了一次决策

走位置(i,j)的左下还是右下

所以

dp[i][j]=max(dp[i+1][j],dp[i][j])+f[i][j]

这就是状态转移方程

但是可以发现

数塔的最后一层的dp值总是等于数组本身

即dp[n][j]=f[n][j](1<=j<=n)

这种就是边界

而动态规划的地推写法总是从这些边界出发

通过状态转移方程扩散到整个dp数组

这样就可以从最底层各位置的dp值出发

不断往上求出每一层各位置的dp值

最后就会得到dp[1][1]

即答案

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
#define maxn 1000
int f[maxn][maxn],dp[maxn][maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=i;j++)
        {
            scanf("%d",&f[i][j]);//输入数塔
        }
    }
    //边界
    for(int j=1;j<=n;j++)
    {
        dp[n][j]=f[n][j];
    }
    for(int i=n-1;i>=1;i--)
    {
        for(int j=1;j<=i;j++)
        {
            dp[i][j]=max(dp[i+1][j],dp[i+1][j+1])+f[i][j];
        }
    }
    printf("%d\n",dp[1][1]);
    return 0;
}

递推写法

自下而上

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值