zoukankan      html  css  js  c++  java
  • 【算法】动态规划

    其实对动态规划并不是特别了解,在网上看到说动态规划是递归时去除重复的运算,提高效率。

    今天结合“数字三角形”这道编程题和书本内容进行学习,题目可以自行百度。

    数字三角形这道题非常经典,通过三个方法来探讨这道题的解题思路~_~

    首先申请两个常数组,a[i][j]存储输入数字三角形的数字,d[i][j]为二次计算存储的值。

    其中状态转移方程是:d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1])。

    方程及各方法的理解方法是直接代入数值跟着走一遍。

    方法一:递归计算
    int solve(int i,int j){
      return a[i][j]+(i==k?0:max(solve(i+1,j),solve(i+1,j+1))); //i==k?此处为边界判断
    }
    注:递归求解的过程有很多重复计算,效率低。得出的解存于a[1][1]中。


    方法二:递推计算
    int i,j;
    for(j=1;j<=n;j++)d[n][j]=a[n][j];
    for(i=n-1;i>=1;--i)
      for(j=1;j<=i;++j)
        d[i][j]=a[i][j]+max(d[i+1][j],d[i+1][j+1]);
    注:递推求解的思路清晰,从最下层一直往上推算,得出最优解,储存于d[1][1]中。时间复杂度是O(n^2)。


    方法三:动态规划(记忆化搜索)
    memset(d,-1,sizeof(d));
    int solve(int i,int j){
      if(d[i][j]>=0)return d[i][j];
      return d[i][j]=a[i][j]+(i==k?0:max(solve(i+1,j),solve(i+1,j+1))); //i==k?此处为边界判断
    }
    注:对比方法一,不难发现d[i][j]的作用是标记重复计算,大大地优化了程序的时间开销。得出的最优解,储存于d[1][1]中。


    送上方法三的解题源码

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    int k;
    int d[101][101],a[101][101];
    int solve(int i,int j){
      if(d[i][j]>=0)return d[i][j];
      return d[i][j]=a[i][j]+(i==k?0:max(solve(i+1,j),solve(i+1,j+1)));
    }
    int main()
    {
      memset(d,-1,sizeof(d));
      int i,j;
      cin>>k;
      for(i=1;i<=k;++i)
        for(j=1;j<=i;++j)
          cin>>a[i][j];
      solve(1,1);
      cout<<d[1][1]<<endl;
      return 0;
    }

    此时发现空间开销一半都是浪费的,可以动态申请二维数组,但相对麻烦。
    动态申请二维数组的方法:
    cin>>row>>col;
    int **p=new int*[row];
    for(int i=0;i<row;++i)
      p[i]=new int[col];

    加油!!!

    部分内容参考刘汝佳老师的《算法竞赛入门经典》

  • 相关阅读:
    设计模式之四 代理模式
    设计模式之四 建造者模式
    设计模式之三 模板模式
    设计模式之二 工厂模式
    如何使用Json-lib
    Java LoggingAPI 使用方法
    设计模式之一 单例模式
    Scrapy教程
    Scrapy简介
    Scrapy安装向导
  • 原文地址:https://www.cnblogs.com/zhenxianluo/p/5222443.html
Copyright © 2011-2022 走看看