『嗨威说』算法设计与分析 - PTA 数字三角形 / 最大子段和 / 编辑距离问题(第三章上机实践报告)

本文索引目录:

一、PTA实验报告题1 : 数字三角形

  1.1  实践题目

  1.2  问题描述

  1.3  算法描述

  1.4  算法时间及空间复杂度分析

二、PTA实验报告题2 : 最大子段和

  2.1  实践题目

  2.2  问题描述

  2.3  算法描述

  2.4  算法时间及空间复杂度分析

三、PTA实验报告题3 : 编辑距离问题

  3.1  实践题目

  3.2  问题描述

  3.3  算法描述

  3.4  算法时间及空间复杂度分析

四、实验心得体会(实践收获及疑惑)

一、PTA实验报告题1 : 数字三角形

  1.1  实践题目:

  1.2  问题描述:

     题意是,题干给你一个三角形(实际上就是半个矩形即下三角形模式或上三角形模式),要求你从顶部计算出到底部最佳的路线,使得经过的数字总和最大。

  1.3  算法描述:

这道题很明显需要用到动态规划的方法,存在重叠子问题,因此我们需要找出这道题的动态转移方程。

我们通过模拟可以发现,样例最佳的行走路径是:

很明显发现,我们并不能通过贪心算法来做这道题,只能用动态规划找出最佳路径。

首先我们需要建立dp数组,定义dp数组的含义为:截至当前位置已走过的数的总和,我们先初始化dp数组。

要确认当前位置,也就需要定义成二维数组,第一个指定为行,第二个指定为具体列。

第二步,我们需要确定动态方程,很明显我们知道:

方程为:dp[i][j] = temp[i][j] + max(dp[i+1][j],dp[i+1][j+1])

以最后两列为例,模拟动规过程:

可以很明显的发现,当下面两格相比,取出最大值,加上自己本身,就是当前的dp值,依照这个思路

我们可以把整个dp过程模拟完成:

到此模拟完成,我们可以很清楚的看到,我们最终想要的答案,就在最顶层,dp[1][1]中,我们只需要固定输出这个值即可得到答案。

第三步,确认我们的填表顺序,从以上的分析角度可以知道,dp方程中当前dp依赖于当前位置的下一行同列以及下一行同列+1的位置,所以需要从下往上填表,分析完毕,按着这个思路敲出代码即可,

完整代码展示如下:

#include<bits/stdc++.h>
using namespace std;
int n,temp[105][105],ans = 0;
int main()
{
    /* input */
    cin>>n;
    for(int i = 1;i<=n;i++)
        for(int j = 1;j<=i;j++)
            cin>>temp[i][j];

    /* 动规转移方程: dp[i][j] = temp[i][j] + max(dp[i+1][j],dp[i+1][j+1]);*/

    /* down to up */
    for(int i = n;i>0;i--)
        for(int j = 1;j<=i;j++)
            temp[i][j] = temp[i][j] + max(temp[i+1][j],temp[i+1][j+1]);

    /* answer */
    cout<<temp[1][1];
 } 

  1.4  算法时间及空间复杂度分析:

   整体算法上看,动态规划是不计算重复子问题,并优化计算过程,防止计算重复,经过分析可知,我们需要O(n^2)时间初始化dp数组,需要O(1/2 * n^2)的时间进行填表,最后输出,总的来看时间复杂度为O(n^2)。

   动态规划需要用到辅助空间二维数组进行填表,表的大小根据问题规模确定,因此空间复杂度是O(n^2)。

二、PTA实验报告题2 : 最大子段和

  2.1  实践题目:

  2.2  问题描述:

    第二题是动态规划的小小压缩版本,题意是说给一段序列,求怎么取一小段,使得加和数最大,也即最大子段和问题。

  2.3  算法描述:

    首先,分析题目选择相应算法,虽然这章都是在学动态规划,但是在平时拿到题目的时候,我们是不知道这是动态规划的,所以需要分析问题,一般这种求最值问题,常常先考虑贪心能否使用,可以发现这道题是可以使用贪心算法的,所以我也使用贪心算法写了一次,但是呢鉴于题目要求需要O(n)的时间复杂度,因此优先考虑动态规划啦。

     第二,初始化dp数组,定义dp数组dp[i]为从1到i中最大的子段和。

      第三,动态规划转移方程,明显可以知道:dp[ i ] = max( dp[ i-1 ] , k ) ; k 为从0-i的加和大于0的子段,一旦小于0就从当前位置重新计段长。

    模拟过程如下:

  因此我们就可以很愉快的写出代码啦。AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,temp[10005],dp[10005],flag = 0,k;
int main()
{
    /* input */
    cin>>n;
    for(int i = 1;i<=n;i++)
    {
        cin>>temp[i];
        if(temp[i] >=0) flag = 1;
    }

    /*    dp[i]:1-i中最大子段和
        k: k从0到i加和大于0的子段,遇到子段小于0的扔掉重新开始计长度*/
    for(int i = 1;i<=n;i++)
    {
        if(k>0) k += temp[i];
        else k=temp[i];
        dp[i] = max(dp[i-1], k);
    }

    /* answer */
    if(flag == 0) cout<<0;
    else cout<<dp[n];
    return 0;
}

  2.4  算法时间及空间复杂度分析:

    算法复杂度跟题目要求一致,时间复杂度为O(n)。

    空间复杂度需要一个一维数组dp,因此空间复杂度也是O(n)

三、PTA实验报告题3 : 编辑距离问题

  3.1  实践题目:

  3.2  问题描述:

    该题目为:题目意思是给定两端英文序列,要求将A序列变成B序列,可以通过对A进行删除、插入、更换任意字符,得到B序列,要求以最少步骤为准。

  3.3  算法描述:

    这道题我和三木在写的时候第一次没有写出来,三木想到一个绝佳的数学公式,用最大长度字符串长减去LCS即为所求,但是答案WA在了第三点,后来发现存在特例无法解决,所以课后我又换了一种方式,这里我讲解的还不是很好,在一个博客我看到一个非常完整很棒的讲解,贴出来给大家看看吧:

  https://blog.csdn.net/weixin_42681158/article/details/89411572

  我的AC代码如下:

#include<bits/stdc++.h>
using namespace std;
int dp[2005][2005];
char a[2005];
char b[2005];
int minval(int a,int b,int c){
    int temp = max(a,b);
    return max(temp,c);
}
int LCS(char *a,char *b)
{
    memset(dp,0,sizeof(dp));
    int lena=strlen(a);
    int lenb=strlen(b);
    for(int i=1;i<=lena;i++)
    {
        for(int j=1;j<=lenb;j++)
        {
            if(a[i-1]==b[j-1])
                dp[i][j]=minval(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]+1);
            else
                dp[i][j]=minval(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]);
        }
    }
    return dp[lena][lenb];
}

int main()
{
    cin>>a;
    getchar();
    cin>>b;
    int maxss =max(strlen(a),strlen(b));

    cout<<maxss-LCS(a,b);

    return 0;
}

  3.4  算法时间及空间复杂度分析:

    由分析易知,时间复杂度和空间复杂度均为O(n^2)

四、实验心得体会(实践收获及疑惑):

  经过第一次实践合作之后,第二次的实践合作愈发顺利,虽然第三题有一小点WA了,不过还是很合作默契的哈哈。(主要是三木太强了)

简单通过书本和博客总结了一下动态规划的一些基本特点如下:

===动态规划问题的特点:

(1)最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。

(2)重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势)

===动规解题的一般思路:

  动态规划所处理的问题是一个多阶段决策问题,一般由初始状态开始,通过对中间阶段决策的选择,达到结束状态。这些决策形成了一个决策序列,同时确定了完成整个过程的一条活动路线(通常是求最优的活动路线)。

  动态规划的设计都有着一定的模式,一般要经历以下几个步骤。

    初始状态→│决策1│→│决策2│→…→│决策n│→结束状态

  (1)划分阶段:按照问题的时间或空间特征,把问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要是有序的或者是可排序的,否则问题就无法求解。

  (2)确定状态和状态变量:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。

  (3)确定决策并写出状态转移方程:因为决策和状态转移有着天然的联系,状态转移就是根据上一阶段的状态和决策来导出本阶段的状态。所以如果确定了决策,状态转移方程也就可写出。但事实上常常是反过来做,根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。

  (4)寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。

如有错误不当之处,烦请指正。

原文地址:https://www.cnblogs.com/WinniyGD/p/11699866.html

时间: 2024-11-10 16:17:53

『嗨威说』算法设计与分析 - PTA 数字三角形 / 最大子段和 / 编辑距离问题(第三章上机实践报告)的相关文章

『嗨威说』算法设计与分析 - 动态规划思想小结(HDU 4283 You Are the One)

本文索引目录: 一.动态规划的基本思想 二.数字三角形.最大子段和(PTA)递归方程 三.一道区间动态规划题点拨升华动态规划思想 四.结对编程情况 一.动态规划的基本思想: 1.1 基本概念: 动态规划算法简单说,利用拆解问题思想,定义问题状态和状态之间的关系,使得问题能够以递推或者是分治的方式去解决. 动态规划算法的基本思想与分治法很相似,将待求解的问题分解为若干个子问题,前一子问题的解,为后一子问题的求解所依赖.在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解

『嗨威说』算法设计与分析 - 算法第二章上机实践报告(二分查找 / 改写二分搜索算法 / 两个有序序列的中位数)

本文索引目录: 一.PTA实验报告题1 : 二分查找 1.1 实践题目 1.2 问题描述 1.3 算法描述 1.4 算法时间及空间复杂度分析 二.PTA实验报告题2 : 改写二分搜索算法 2.1 实践题目 2.2 问题描述 2.3 算法描述 2.4 算法时间及空间复杂度分析 三.PTA实验报告题3 : 两个有序序列的中位数 3.1 实践题目 3.2 问题描述 3.3 算法描述 3.4 算法时间及空间复杂度分析 四.实验心得体会(实践收获及疑惑) 一.PTA实验报告题1 : 二分查找 1.1 实践

揭露动态规划真面目——算法第三章上机实践报告

算法第三章上机实践报告 一.        实践题目 7-2 最大子段和 (40 分) 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值.当所给的整数均为负数时,定义子段和为0. 要求算法的时间复杂度为O(n). 输入格式: 输入有两行: 第一行是n值(1<=n<=10000): 第二行是n个整数. 输出格式: 输出最大子段和. 输入样例: 在这里给出一组输入.例如: 6 -2 11 -4 13 -5

算法第三章上机实践报告

实践题目 7-1 数字三角形 (30 分) 给定一个由 n行数字组成的数字三角形如下图所示.试设计一个算法,计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大. 输入格式: 输入有n+1行: 第 1 行是数字三角形的行数 n,1<=n<=100. 接下来 n行是数字三角形各行中的数字.所有数字在0..99 之间. 输出格式: 输出最大路径的值. 输入样例: 在这里给出一组输入.例如: 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5

算法第三章上机实践报告之数字三角形

1.实践题目 7-1 数字三角形 (30 分) 给定一个由 n行数字组成的数字三角形如下图所示.试设计一个算法,计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大. 输入格式: 输入有n+1行: 第 1 行是数字三角形的行数 n,1<=n<=100. 接下来 n行是数字三角形各行中的数字.所有数字在0..99 之间. 输出格式: 输出最大路径的值. 输入样例: 在这里给出一组输入.例如: 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6

算法第三章上机实践报告——动态规划

1.实践题目 7-1 数字三角形 (30 分) 给定一个由 n行数字组成的数字三角形如下图所示.试设计一个算法,计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大. 输入格式: 输入有n+1行: 第 1 行是数字三角形的行数 n,1<=n<=100. 接下来 n行是数字三角形各行中的数字.所有数字在0..99 之间. 输出格式: 输出最大路径的值. 输入样例: 在这里给出一组输入.例如: 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6

09.19算法第二章上机实践报告

算法第二章上机实践报告 https://edu.cnblogs.com/campus/gdwywm/se1803/homework/7608 1.实践题目 7-3 两个有序序列的中位数 https://pintia.cn/problem-sets/1173827583729741824/problems/1173827629514764290 2.问题描述 已知有两个等长的非降序序列S1, S2, 设计函数求S1与S2并集的中位数.有序序列A ?0 ?? ,A ?1 ?? ,?,A ?N−1 ?

贪心算法?我全都要!——算法第四章上机实践报告

算法第四章上机实践报告 一.        实践题目 4-1 程序存储问题 (90 分) 设有n 个程序{1,2,…, n }要存放在长度为L的磁带上.程序i存放在磁带上的长度是 li,1≤i≤n. 程序存储问题要求确定这n 个程序在磁带上的一个存储方案, 使得能够在磁带上存储尽可能多的程序. 对于给定的n个程序存放在磁带上的长度,计算磁带上最多可以存储的程序数. 输入格式: 第一行是2 个正整数,分别表示文件个数n和磁带的长度L.接下来的1行中,有n个正整数,表示程序存放在磁带上的长度. 输出

二分查找真的那么简单吗?——算法第二章上机实践报告

一.        实践题目 改写二分搜索算法 (20 分) 题目来源:<计算机算法设计与分析>,王晓东 设a[0:n-1]是已排好序的数组,请改写二分搜索算法,使得当x不在数组中时,返回小于x的最大元素位置i和大于x的最小元素位置j.当搜索元素在数组中时,i和j相同,均为x在数组中的位置. 输入格式: 输入有两行: 第一行是n值和x值: 第二行是n个不相同的整数组成的非降序序列,每个整数之间以空格分隔. 输出格式: 输出小于x的最大元素的最大下标i和大于x的最小元素的最小下标j.当搜索元素在