动态规划-入门篇

动态规划

维基百科上对于动态规划是这么定义的:

dynamic programming is a method for solving a complex problem by breaking it down into a collection of simpler subproblems, solving each of those subproblems just once, and storing their solutions.
Ref: Dynamic programming

也就是说,动态规划一定是具备了以下三个特点:

  1. 把原来的问题分解成了几个相似的子问题。(强调“相似子问题”)
  2. 所有的子问题都只需要解决一次。(强调“只解决一次”)
  3. 储存子问题的解。(强调“储存”)

那么如何判断某个问题是否可以用动态规划的方法解决呢

若求解问题的最优性原理成立,则可以用动态规划的方法解决

无论过程的初始状态和初始决策是什么,其余的决策都必须相对于初始决策所产生的状态构成一个最优决策序列 下面通过几个例子来学习动态规划吧

1.数塔问题

问题描述

        7 
      3   8 
    8   1   0 
  2   7   4   4 
4   5   2   6   5

有一个r行的数塔,数塔上有若干数字。问从数塔的最高点到底部,在所有的路径中,经过的数字的和最大为多少?
如上图,是一个5行的数塔,其中7—3—8—7—5的路径经过数字和最大,为30。

解法思路

面对数塔问题,使用贪心算法显然是行不通的,比如给的样例,如果使用贪心算法,那选择的路径应当是7—8—1—7—5,其经过数字和只有28,并不是最大。而用深搜DFS很容易算出时间复杂度为O(2N-1)(因为每个数字都有向左下和右下两种选择),行数一多必定超时。

所以,数塔问题需要使用动态规划算法。

①我们可以从上往下遍历。

可以发现,要想经过一个数字,只能从左上角或右上角的数字往下到达。

所以显然,经过任一数字A时,路径所经过的数字最大和——是这个数字A左上方的数字B以及右上方的数字C两个数字中,所能达到的数字最大和中较大的那一个,再加上该数字A。

故状态转移方程为: [公式]

其中i,j表示行数和列数,dp表示储存的最大和,num表示位置上的数字。

[公式] 表示左上角, [公式] 表示右上角。

以样例来说明:在经过第三行的数字1时,我们先看它左上角的数字3和右上角的数字8其能达到的最大和。3显然只有7—3一条路径,故最大和是10;8显然也只有7—8一条路径,其最大和是15;两者中较大的是15,故经过1所能达到的最大和是15+1=16。

这样一步步向下遍历,最后经过每一个位置所能达到的最大和都求出来了,只要从最底下的一行里寻找最大值并输出即可。

②我们也可以从下往上遍历。

一条路径不管是从上往下走还是从下往上走,其经过的数字和都是一样的,所以这题完全可以变成求——从最底层到最高点所经过的最大数字和。

其写法与顺序遍历是一样的,只是状态转移时,变成从该数字的左下角和右下角来取max了。逆序遍历的写法相比于顺序遍历优点在于:少了最后一步求最后一行max的过程,可以直接输出最高点所储存的值。

代码实现

#include <stdio.h>
#include <algorithm>
using namespace std;//这里以顺序遍历为例
int num[1005][1005];//用于储存数塔每个位置的数字
int dp[1005][1005];//用于储存经过数塔每个位置所能达到的最大和
int main()
{
    int r;
    scanf("%d",&r);//输入数塔行数
    for(int i=1;i<=r;i++)
        for(int j=1;j<=i;j++)
            scanf("%d",&num[i][j]);
    //输入数塔数据,注意i和j要从1开始,防止数组越界
    for(int i=1;i<=r;i++)//共计r行
        for(int j=1;j<=i;j++)//每行有j个数字
            dp[i][j]=max(dp[i-1][j],dp[i-1][j-1])+num[i][j];
    //经过该数字的最大和,为左上角和右上角中的max,再加上该数字
    int ans=0;
    for(int i=1;i<=r;i++)
        ans=max(ans,dp[r][i]);//从最后一行中找到最大数
    printf("%d\n",ans);//就是答案
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fluxation/p/12693486.html
今日推荐