算法学习笔记三:(dp)最长连续子序列
题目描述
给定 K 个整数的序列{ N1, N2, …, NK } ,其任意连续子序列可表示为{ Ni, Ni+1,…,Nj} ,其中1 <= i<= j <= K。最大连续子序列是所有连续子序列中元素和最大的一个,例如给定序列{ -2, 11, -4, 13, -5, -2 } ,其最大连续子序列为{ 11, -4, 13 } ,最大和为20。编写程序得到其中最大子序列的和并输出该子序列的第一个和最后一个元素的下标。
输入
测试输入包含若干测试用例,每个测试用例占2 行,第 1 行给出正整数 K( <100000) ,第 2 行给出 K 个整数,每个整数的范围-10000至10000 ,中间用空格分隔。当K 为0 时,输入结束,该用例不被处理。
输出
对每个测试用例, 在 1 行里输出最大和、 最大连续子序列的第一个和最后一个元素的下标,中间用空格分隔。 如果最大连续子序列不唯一, 则输出序号 i 和 j 最小的那个(如输入样例的第 2、3组)。若所有 K 个元素都是负数,则定义其最大和为0,输出"0 0 0"。
样例输入
8
6 -2 11 -4 13 -5 -2 10
20
-10 1 2 3 4 -5 -23 3 7 -21 6 5 -8 3 2 5 0 1 10 3
8
-1 -5 -2 3 -1 0 -2 0
4
-1 -2 -4 -3
0
样例输出
27 0 7
27 10 19
3 3 3
0 0 0
思想:首先此问题若用暴力解法,枚举左端点和右端点需要O(n^2)的时间复杂度这样对n为10 ^5的数据来说无法承受。因此可以用动态规划来解决。
第一步:设置数组dp表示为以a[i]作为末尾的连续序列的最大和。样例:序列-2 11 -4 13 -5 -2,下标为0,1,2,3,4,5那么有
dp[0]=-2; dp[1]=11; dp[2]=7(11+(-4)=7); dp[3]=20(11+(-4)+13=20); dp[4]=15; dp[5]=13.
第二步:由于dp[i]要求是必须以a[i]为结尾的连续队列,所以只有两种情况:
①这个最大和的连续序列只有一个元素,即从a[i]开始到a[i]结束。
②这个最大和的连续序列有多个元素,即从前面某处a[p]开始(p<i)一直到a[i]结束。
对于第一种情况,最大和就是a[i]本身。
对于第二种情况,最大和就是dp[i-1]+a[i].
可得到状态转移方程:
dp[i]=max{a[i],dp[i-1]+a[i]}.
最后遍历dp数组,其中最大值就是所求。奉上代码.
#include<iostream> using namespace std; struct node { int x,y;//x为起点,y为终点 long long a; }; int main() { int k; while(scanf("%d",&k)!=EOF) { long long a[10010]; if(k==0) break; int i,max=0; for(i=0;i<k;i++) cin>>a[i]; node dp[10010]; dp[0].a=a[0]; dp[0].x=0; dp[0].y=0; for(i=1;i<k;i++) { if(a[i]>dp[i-1].a+a[i]) { dp[i].a=a[i]; dp[i].x=i; dp[i].y=i; } else { dp[i].a=dp[i-1].a+a[i]; dp[i].x=dp[i-1].x; dp[i].y=i; } } for(i=1;i<k;i++) { if(dp[i].a>dp[max].a) max=i; } if(dp[max].a<0) cout<<"0 0 0"<<endl; else cout<<dp[max].a<<" "<<dp[max].x<<" "<<dp[max].y<<endl; } return 0; }
- |算法讨论|状压DP/位运算 学习笔记
- 每天学习一算法系列(22)(在字符串中找出连续最长的数字串,并把这个串的长度返回)
- 学习笔记-最长上升子序列问题
- 关于最长上升子序列的nlogn时间复杂度的DP算法详解(易懂)
- 算法学习十一----连续最长的数字串
- 【最长连续子序列和】三种复杂度的算法
- DP之最长上升子序列O(n*logn)算法
- 【算法学习笔记】67.状态压缩 DP SJTU OJ 1383 畅畅的牙签袋
- 算法练习--- DP 求解最长上升子序列(LIS)
- 【算法学习笔记】84.序列DP 松弛+代价处理 CODE_VS 1048 石子归并
- 【算法学习笔记】62.状态压缩 DP SJTU OJ 1088 邮递员小F
- 笔试算法学习--dp规划(最长非递增子序列)
- 【算法学习笔记】85.破环为链 序列DP 松弛+代价 SJTU OJ 1073 能量项链
- 最长连续子序列和的线性算法及其他算法
- [学习笔记]浅谈LIS(最长上升子序列)与网络流
- DP算法之最长上升子序列
- 最长公共子串算法的学习笔记
- DP之最长上升子序列O(n*logn)算法
- 算法学习之动态规划--最长上升子序列
- 算法练习--- DP 求解最长上升子序列(LIS)