zoukankan      html  css  js  c++  java
  • 动态规划——数字三角形(递归or递推or记忆化搜索)

    动态规划的核心就是状态和状态转移方程。

    对于该题,需要用抽象的方法思考,把当前的位置(i,j)看成一个状态,然后定义状态的指标函数d(i,j)为从格子出发时能得到的最大和(包括格子本身的值)。

    在这个状态定义下,原问题的解就是d(i,j).

    下面看一下不同状态之间如何转移。从格子(i,j)出发有两种策略。如果向左走,则到(i+1,j)后需要求“从(i+1,j)出发能得到的最大和”这一问题,即d(i+1,j)。

    类似的,往右走之后需要求解d(i+1,j+1).由于可以在这两个决策中自由选择,所以应选择其中较大者。换句话说就是得到状态转移方程

    d(i,j)=a(i,j)+Max(d(i+1,j),d(i+1,j+1))

    这样就保证了子树的最优,这个性质称为最优子结构。

    用直接递归的方法计算状态转移方程,效率往往十分低下。其原因是相同的子问题被重复计算了多次。

    因此我们对其优化采用了递推算法或者采用记忆搜索的方式。

    递推计算就是把每个问题直接罗列出来,因此不会重复。

    记忆搜索的程序依然是递归的,但是把计算结果放在了数组d中。开始将所有状态置为-1,只要是计算过的状态就就变成非负,因此只要判断是否d[i][j]>=0,就知道它是否计算过。

    #include<iostream>
    #include<string>
    using namespace std;
    void input(int a[][10],int n)
    {
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<=i;j++)
            {
                cin>>a[i][j];
            }
        }
    }
    int max(int a,int b)
    {
        if(a>b)
            return a;
        else
            return b;
    }
    /*******************i表示当前行数,j表示当前列数,n表示规格****************************/
    /**********d(i,j)表示状态,d(i,j)=a(i,j)+Max(d(i+1,j),d(i+1,j+1))为状态转移方程*********/
    int d(int a[][10],int i,int j,int n)
    {
        if(i>=n)
            return 0;
        else
        {
            return a[i][j]+max(d(a,i+1,j,n),d(a,i+1,j+1,n));
        }
    }
    /**************采用递推计算,i表示当前行数,j表示当前列数,n表示规格**********************************/
    int d1(int a[][10],int n)
    {
        int i,j;
        int b[10][10];
        for(i=0;i<=n;i++)
            b[n][i]=0;        //将b(n,0~n)状态全部赋值为0
        for(i=n-1;i>=0;i--)
        {
            for(j=0;j<=i;j++)
            {
                b[i][j]=a[i][j]+max(b[i+1][j],b[i+1][j+1]);
            }
        }
        return b[0][0];
    }

    /*************采用记忆化搜索*************************/
    int d2(int a[][10],int b[][10],int i,int j,int n)
    {
        if(b[i][j]>=0)
            return b[i][j];
        else
        {
            if(i>=n)
                return 0;
            else
                return b[i][j]=a[i][j]+max(d2(a,b,i+1,j,n),d2(a,b,i+1,j+1,n));
        }
    }
    int main()
    {

        int a[10][10];
        int b[10][10];
        memset(b,-1,sizeof(b));
        int n;
        cout<<"请输入总共有多少行"<<endl;
        cin>>n;
        input(a,n);
        cout<<d(a,0,0,n)<<endl;
        cout<<d1(a,n)<<endl;
        cout<<d2(a,b,0,0,n)<<endl;
        return 0;
    }

  • 相关阅读:
    生活
    通俗易懂----尾递归
    。。。
    调用startActivityForResult,onActivityResult无响应的解决办法
    安卓官方ViewPager与android.support.design.widget.TabLayout双向交互联动切换 。
    1、面向对象以及winform的简单运用(开篇)
    15、C#基础整理(递归)
    14、C#基础整理(函数)
    13、C#基础整理(枚举)
    12、C#基础整理(结构体)
  • 原文地址:https://www.cnblogs.com/hutao886/p/4503279.html
Copyright © 2011-2022 走看看