第三章实践心得

  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】

posted @ 2019-10-23 00:29  johnson_25  阅读(107)  评论(0编辑  收藏  举报