动态规划-数塔问题

前言

动态规划算法解决一些问题,算法的时间复杂度事比较低的。是一种用空间换时间的算法设计思想。

基本结构

F(n)
A[0]=A[1]<-1
for i<-2 to n do
  状态转移方程
return A[n]

基本思想

  • 动态规划就是用一种类似于表(通常用数组)记录子问题的解,以便保存和以后的检索以从最简单问题的解填起,以自底向上的方式填表。
  • 这就保证了,当我们求解一个子问题的时候,所有与子相关的子问题,都可以从表中直接取用,而不必重新计算。
  • 动态规划算法策略需要全面考虑不同的情况分别进行决策, 并通过多阶段决策来最终解决问题。
  • 在各个阶段采取决策后,会不断决策出新的数据,直到找到最优解。每次决策依赖于当前状态, 又随即引起状态的转移。
  • 一个决策序列就是在变化的状态中产生出来的,故有“动态”的含义。所以,这种多阶段决策最优化的解决问题的过程称为动态规划。

基本步骤

  1. 找出最优解的性质并刻划其结构特征
  2. 递归的定义最优值
  3. 以自底向上的方式计算出最优值
  4. 根据计算最优值时得到的信息构造最优解

优点

  • 子问题重叠性质;
  • 动态规划用空间换取时间,在有大量重叠子问题的时候其优势才能充分体现出来。

数塔问题

问题

有形如下图的一个数塔,从顶部出发,在每一结点可以选择向左走或是向右走,一直走到底层,要求找出一条路径,使路径上的数值和最大
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k9tqmB1e-1585659176593)(DACBB9061D824FEBBBB956E9E6C9306E)]

问题分析

枚举

数塔层数为n,枚举的路径2^(n-1)条

贪心法自上而下

9-15-8-9-10

贪心法自下而上

19 2 10 12 9

口算

9->12->10->18->10

得不到正确的答案[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7NmYggiW-1585659176594)(D831A9A52BC04F7BA9DDA178DA66FC9B)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jUA6aWjV-1585659176595)(D8992C312EDD46B0A90915B587260F0C)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ffBkcLqx-1585659176596)(F9F4783B95054D1488C5E862F9F21CC1)]

#include<cstdio>
#include <cstring>
const int maxn=110;
int main()
{
    int n,m;
    int a[maxn][maxn],b[maxn][maxn];
    scanf("%d",&n);
    while(n--)
    {
        memset(b,0,sizeof(b));
        scanf("%d",&m);
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=i;j++)
 
                {
                    scanf("%d",&a[i][j]);
                }
        }
        for(int i=1;i<=m;i++)
        {
            b[m][i]=a[m][i];
        }
        for(int i=m-1;i>0;i--)
        {
            for(int j=1;j<=i;j++)
            {
                if(b[i+1][j]>b[i+1][j+1])
                    b[i][j]=a[i][j]+b[i+1][j];
                else
                    b[i][j]=a[i][j]+b[i+1][j+1];
            }
        }
        printf("%d\n",b[1][1]);
    }
    return 0;
}

Java实现

import java.util.Scanner;


public class Test {
    public static void main(String[] args) {
        Scanner sc  = new Scanner(System.in);
        int n = sc.nextInt();
        int [][]  num = new int [n+2][n+2];
        int [][]  max = new int [n+2][n+2];
        for (int i = 1; i <=n; i++) {
            for (int j = 1; j <=i; j++) {
                num[i][j]=sc.nextInt();
            }
        }
        for (int i = 1; i <=n; i++) {
            for (int j = 1; j <=i; j++) {
                //if(j+1>=n+2) continue;
                num[i][j]=Math.max(num[i-1][j-1]+num[i][j],num[i-1][j]+num[i][j]);
            }
        }
        int max1 = 0;
        for (int i = 1; i <=n+1; i++) {
            max1=Math.max(num[n][i], max1);
        }
        System.out.println(max1);
    }
}



优化算法(伪代码)

main()
{int a[50][50][3],i,j,n;
input(n);
for( i=1 ;i<=n;i++)
for (j=1;j<=i;j++){ 
        input(a[i][j][1]);
        a[i][j][2]=a[i][j][1];
        a[i][j][3]=0;}
for (i=n-1 ; i>=1;i--)
for (j=1 ;j>= i ;j++)
if (a[i+1][j][2]>a[i+1][j+1][2]) {
        a[i][j][2]=a[i][j][2]+a[i+1][j][2];      
        a[i][j][3]=0;}  
    else {
        a[i][j][2]=a[i][j][2]+a[i+1][j+1][2];        
        a[i][j][3]=1;}
        print('max=,a[1][1][2]);
        j=1;
       for( i=1 ;i<= n-1;i++){
        print(a[i][j][1],->);
        j=j+a[i][j][3]; 
        }print (a[n][j][1]);
}

总结

动态规划=贪婪策略+递推(降阶)+存储递推结果。贪婪策略,递推关系都是在“线性”的解决问题。通俗的说动态规划事“带决策的多阶段,多方位的递推算法”。

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值