动态规划

LeetCode53 最大子序和

假如想象 提交于 2019-12-01 23:42:13
LeetCode53 最大子序和 题目 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输出: 6 解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。 进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。 来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/maximum-subarray 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 分析 做这题是因为当时算法课讲到动态规划,所以先做做动态规划的简单题。这题容易理解,但是我一直没太懂哪里用到了动态规划。动态规划不是先求解小问题,然后大问题利用小问题求得的解来继续运算。直到求得问题的解 代码 class Solution { public: int maxSubArray(vector<int>& nums) { int sum=0; int ans=nums[0]; for(int i=0;i<nums.size();i++){ if(sum>0){ sum+=nums[i]; }else{ sum=nums[i]; } ans=ans>sum?ans:sum; } return ans; } };

动态规划经典例子——编辑距离问题

不打扰是莪最后的温柔 提交于 2019-12-01 20:39:54
问题描述:   两个字符串,一个是起点字符串,另一个是终点。   例如,起点字符串ddl到终点字符串de的转换步骤如下:   ddl->del->def。   编辑距离为2。 算法分析:    首先考虑上面例子中ddl的第一个字符和def的第一个字符, 它 们是一样的,所以只需要计算a[2...lengthA]和b[2...lengthB](dl和ef)之间的距离即可。   若 两个字符串的第一个字符不同,例如adl和def,可以三选一: 把终点串的第一个字符插入到起点串的第一个字符之前(adl->dadl),然后计算a[1...lengthA]和b[2...lengthB](dadl和def)的距离即可; 删除起点串的第一个字符(adl->dl),然后计算a[2...lengthA]和b[1...lengthB](dl->def)的距离即可; 修改起点串的第一个字符成终点串的第一个字符(adl->ddl),然后计算a[2...lengthA]和b[2...lengthB](dl和ef)的距离即可。   考虑起点 串的第i个字符和终点串的第j个字符的话也是一样的。 当不考虑起点串的前i-1字符和终点串的前j-1个字符, 如果起点串的第i个字符和终点串的第j个字符相等,即a[i-1] = b[j-1],则只需要计算a[i...lengthA]和b[j...lengthB

第三章上机实践报告

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-01 20:39:23
1、实践题目 7-2 最大子段和 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。 要求算法的时间复杂度为O(n)。 2、问题描述 由于要求时间复杂度是O(n),因此递归的方法被砍,只能另外谋求生计 当时间复杂度为O(n),第一反应是用一个for循环,但是如何能只用一个for循环得出结果呢? 自然想到在循环遍历的时候将当前最优解存起来,最后进行一个比较,选择最好的那个解 于是就用到动态规划法来解决问题。 3、算法描述 算法的核心在于递归方程 MaxSum[i] = ele[i] i=0 MaxSUm[i] = max{ele[i], ele[i] + MaxSum[i - 1]} 0 < i < n 因此着重讲解递归方程的求得过程 首先对原输出和辅助记录空间进行定义 ele[i]:序列的第i - 1个元素,i从0开始(数组下标) MaxSum[i]:从ele[0],以ele[i]为尾数的最大子段和(可能不包括ele[0],ele[1]....ele[i - 1]) 然后我们分析最开始的情况,从第一个数开始 第一个数有两种情况,小于等于或0大于0。若小于等于0,则最大子段和 必不包括 它,因为它是第一个数。如果是大于0,则最大子段和 有可能 包括它。

动态规划训练之十七

拜拜、爱过 提交于 2019-12-01 20:23:01
https://loj.ac/problem/10177 今天的考试题目中有单调队列优化dp的,感觉不太熟练,所以练几手题 其实这题 就是今天的T2!!!! 首先是dp很明确 dp[i,0]表示处理了前i个位置,并且第i个位置不选的最大值 dp[i,1]表示处理了前i个位置,并且第i个位置要选的最大值 明显dp[i,0]=max(dp[i-1,0],dp[i-1,1]); dp[i,1]=dp[j,0]+sum[i]-sum[j],(i-k<=j<i) 又是维护移动区间,维护递减的单调队列 code by wzxbeliever: #include<bits/stdc++.h> #define ll long long #define il inline #define ri register int #define lowbit(x) x&(-x) using namespace std; const int maxn=1e5+5; int n,k,head=1,tail=1; il ll maxl(ll a,ll b){if(a>b)return a;return b;} ll num[maxn],a[maxn],sum[maxn],dp[maxn][2]; int main(){ scanf("%d%d",&n,&k); for(ri i=1;i<=n;i++)scanf("

第三章上机实践报告

筅森魡賤 提交于 2019-12-01 20:11:48
7-3 编辑距离问题 (30 分) 设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。 将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。 对于给定的字符串A和字符串B,计算其编辑距离 d(A,B)。 输入格式: 第一行是字符串A,文件的第二行是字符串B。 提示:字符串长度不超过2000个字符。 输出格式: 输出编辑距离d(A,B) 输入样例: 在这里给出一组输入。例如: fxpimu xwrs 输出样例: 在这里给出相应的输出。例如: 5 题目描述:通过研读题目,我们不难发现,是要求我们输入两个字符串,并且求出他们的编辑距离:①将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。②字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。 算法描述:我们假设有字符串A(A.length()== a)和字符串B(B.length()== b).对于一个字符串A来说,A[1]~A[a]到B的编辑距离取决于A[1]~A[a-1]到B的编辑距离。同时,对于一个字符串来说,A到B[1]~B[b]的编辑距离也取决于A到B[1]~B[b-1]的编辑距离。那么

动态规划-编辑距离

ε祈祈猫儿з 提交于 2019-12-01 20:04:56
设A和B是2个字符串。要用最少的字符操作将字符串A转换为字符串B。这里所说的字符操作包括 (1)删除一个字符; (2)插入一个字符; (3)将一个字符改为另一个字符。 将字符串A变换为字符串B所用的最少字符操作数称为字符串A到 B的编辑距离,记为d(A,B)。 对于给定的字符串A和字符串B,计算其编辑距离 d(A,B)。 输入格式: 第一行是字符串A,文件的第二行是字符串B。 提示:字符串长度不超过2000个字符。 输出格式: 输出编辑距离d(A,B) 输入样例: 在这里给出一组输入。例如: fxpimu xwrs 输出样例: 在这里给出相应的输出。例如: 5 假设序列S和T的长度分别为m和n, 两者的编辑距离表示为dp[m][n]. 则对序列进行操作时存在以下几种情况: a, 当S和T的末尾字符相等时, 对末尾字符不需要进行上述定义操作中(亦即"编辑")的任何一个, 也就是不需要增加计数. 则满足条件: dp[m][n] = dp[m - 1][n - 1]. b, 当S和T的末尾字符不相等时, 则需要对两者之一的末尾进行编辑, 相应的计数会增加1. b1, 对S或T的末尾进行修改, 以使之与T或S相等, 则此时dp[m][n] = dp[m - 1][n - 1] + 1; b2, 删除S末尾的元素, 使S与T相等, 则此时dp[m][n] = dp[m - 1][n] + 1

第三章上机实践报告

↘锁芯ラ 提交于 2019-12-01 20:02:59
1.实践题目 7-2 最大子段和 (40 分) 给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。要求算法的时间复杂度为O(n)。 2.问题描述 题目求的是最大字段和,且要求时间复杂度为O(n),应运用动态规划法将之前的运算结果存下,从而降低时间复杂度。 3.算法描述 运用动态规划的精髓是写出其动态规划递归式,temp[i]=max{b[i-1]+a[i],a[i]} (1<=i<=n),其中temp的作用是记录当前的和,若比当前的sum大则记录到sum中,最后输出的sum便是最大值。 int MaxSum(int n, int a[]) { int sum = 0, temp = 0; for (int i = 1; i <= n; i++) { if (temp > 0) temp += a[i]; else temp = a[i]; if (temp > sum) sum = temp; } return sum; } 4.算法时间及空间复杂度分析 时间复杂度:算法中只有一个for循环,因此为O(n) 空间复杂度:算 法中用到了一个和原序列等大的辅助空间,因此为O(n) 5.心得体会 这次的第三章上机实践一共做了两道题目

动态规划训练之十六

别来无恙 提交于 2019-12-01 19:26:58
https://www.luogu.org/problem/P4072 是 P2212(动态规划训练之十五) 的提升版 全程抄袭题解 首先 化简方差: 这样直接转移就是N×N×N的复杂度,也就是P2212 考虑优化 code: #include<cstring> #include<cstdio> #include<queue> #define N 3005 #define int long long int f[N][N]; int que[N]; int sl[N]; int l[N]; int n,m; int min(int a,int b){return a<b?a:b;} double slope(int u,int j,int k){return double(f[u][j]-f[u][k]+sl[j]*sl[j]-sl[k]*sl[k])/(double)(sl[j]-sl[k]);} int main(){ scanf("%lld%lld",&n,&m); memset(f,0x3f,sizeof(f)); for(int i=1;i<=n;++i)scanf("%lld",&l[i]); for(int i=1;i<=n;++i)sl[i]=sl[i-1]+l[i]; int h,t; f[0][0]=0; for(int i=1;i<=n;i++)f[1][i]

动态规划-最低通行费

☆樱花仙子☆ 提交于 2019-12-01 18:49:17
一个商人穿过一个N×N的正方形的网格,去参加一个非常重要的商务活动。他要从网格的左上角进,右下角出。每穿越中间1个小方格,都要花费1个单位时间。商人必须在(2N-1)个单位时间穿越出去。而在经过中间的每个小方格时,都需要缴纳一定的费用。 这个商人期望在规定时间内用最少费用穿越出去。请问至少需要多少费用? 注意:不能对角穿越各个小方格(即,只能向上下左右四个方向移动且不能离开网格)。 输入格式: 第一行是一个整数,表示正方形的宽度N (1≤N<100); 后面N行,每行N个不大于100的整数,为网格上每个小方格的费用。 输出格式: 至少需要的费用。 输入样例: 5 1 4 6 8 10 2 5 7 15 17 6 8 9 18 20 10 11 12 19 21 20 23 25 29 33 输出样例: 109 样例中,最小值为109=1+2+5+7+9+12+19+21+33。 商人必须在(2N-1)个单位时间穿越出去 而正方形网格边长为N,商人初始位置在左上角 则商人只能往右或者往下走 我们可以认为商人达到某个位置时立刻交费(题目是经过,不过没影响),当商人到某一位置时,所用的最小费用为该位置的费用加上该位置的左边和上边中费用较小的一边,如果在边界(第一行或第一列)则直接取(左边或上边),不用比较 定义二维数组 a[i][j] 表示到位置第i行第j列, a[i][j]

算法第三章上机实践报告

不问归期 提交于 2019-12-01 18:47:06
1. 实践题 目: 数字三角形 2. 问题描述: 给定一个由 n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大。 3. 算法描述:用二维数组 a[100][100] 储存数字三角形,以下三角方式输入。 m[i][j] 用于存储从 a[i][j] 至底部的数字和最大路径;计算从底部至底的数字和最大的路径,求顶部 7(a[1][1]) 至底部最大路径 m[1][1] 与 m[2][1],m[2][2] 相关 . 根据动态规划思想得出递归方程: m[i][j] = max(m[i+1][j], m[i+1][j+1]) + a[i][j] for(int i = n; i >= 1; i--) { for(int j = 1; j <= i; j ++) { m[i][j] = max(m[i+1][j], m[i+1][j+1]) + a[i][j]; } } cout << m[1][1] << endl; View Code 4. 算法时间及空间复杂度分析: 时间复杂度:两个 for 循环: O(n^2); 空间复杂度:两个二维数组: O(n^2). 5. 心得体会: 刚开始接触动态规划觉得递归方程好难写,需要多多实践才能熟练掌握。但动态规划思想与递归相结合,将复杂问题简单化。 来源