• 第三章实践心得


    1. 给定一个由 n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总最大

    思路:将三角形存在一个二维数组中,然后从倒数第二层往上,每次寻找下一层到此层的最大值,记录在dp【i】【j】 中,一层一层填表,最后dp[[1][1]就是最大值

    代码:

    #include<iostream>

    #include<string.h>

    #include<algorithm>

    using namespace std;

     

    int G[110][110];

    int dp[110][110];

    int main()

    {

        

        int n;

        cin>>n; 

        for(int i=1;i<=n;i++)

        {

            for(int j=1;j<=i;j++)

            {

                cin>>G[i][j];

                if(i==n)

                {

                    dp[i][j] = G[i][j];

                }

             }

        }

     

        for(int j=n-1;j>=1;j--)

        {

            

            for(int i=1;i<=j;i++)

            {

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

            }

        }

        cout<<dp[1][1];

    }

    1. 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0

    思路: 用dp[i] 记录以a[i] 为结尾的最大字段和: 当到a[i] 时,可以选择a[i] 自己独自成段,也可以与前面子段拼合。每到一个a[i] 1就寻找此前dp[1] ~ dp[i-1]的最大值,这个值就是要衔接a[i] 的子段。 最后用一个数字记录所有dp[i]的最大值

     

    代码:

    #include<iostream>

    #include<string.h>

    #include<algorithm>

    using namespace std;

     

    int main()

    {

        int n , x , maxv = 0, dp , dp_pre = 0 ;

        cin>>n;

        for(int i=1;i<=n;i++)

        {

            cin>>x;

            dp = max(dp_pre+x,x);

            if(dp>maxv)

            {

                maxv = dp;

            }

            dp_pre = dp;

        }

        cout<<maxv;

     }

    1. 设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。 将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。 对于给定的字符串A和字符串B,计算其编辑距离 d(A,B)

    思路: 两个字符串,A1,A2,A3,A4 和 B1,B2,B3,B4;

    1): 如果A4 == B4 ,那么就可以直接比较 A1,A2,A3 和B1,B2,B3这两个子段的。

    2) 如果A4!= B4 , 那么我们就假设

    2.1) 删掉A4,然后 A1,A2,A3 与B1,B2,B3,B4的比较情况

    2.2)  删掉B4,然后 A1,A2,A3,A4 与B1,B2,B3的比较情况

    2.3)  将A4换成B4,然后比较接下来的A1,A2,A3 和B1,B2,B3

    然后找到2.3),2.2) , 2.1) 中的最小值,这个就是当前的最优解。

    比较晚A4,B4,接下来进行相同操作

    代码:

    #include<iostream>

    #include<string.h>

     

    using namespace std;

    int dp[2010][2010];

    int main()

    {

        string s1;

        string s2;

        cin>>s1;

        cin>>s2;

        for(int i=0;i<=s1.size();i++)

        {

            dp[i][0] = i;

        }

        for(int j=0;j<=s2.size();j++)

        {

            dp[0][j] = j;

        }

        

        for(int i=1;i<=s1.size();i++)

        {

            for(int j=1;j<=s2.size();j++)

            {

                if(s1[i-1] != s2[j-1])

                {

                    dp[i][j] = min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]+1));

                }

                else

                {

                    dp[i][j] = min(dp[i-1][j]+1,min(dp[i][j-1]+1,dp[i-1][j-1]));

                 }

            }

        }

        cout<<dp[s1.size()][s2.size()];

        

     

    }

    实践心得: 动态规划最重要的就是找到递推关系,通常是当前解继承自上一解,一级一级往后,就可以得到答案。有些题是是找子序列的,这种就是要找多有dp的最大值,而不是dp【n】

  • 相关阅读:
    CSS Class 选择器
    CSS ID 选择器
    一个可以兼容各种数据库事务的使用范例
    参数化构造的通用查询方法
    QUI操作超时弹出登录窗口登录的处理方式
    一款代码生成器的妙用
    mongoDB操作命令及mongoDB的helper
    记录asp.net网站停止运行原因的代码
    一个JS版本的MD5
    获取地理位置的html5代码
  • 原文地址:https://www.cnblogs.com/aresjohnson/p/11723639.html
Copyright © 2020-2023  润新知