hdu-1024 多段子段最大和问题
来源:互联网 发布:linux把ip写入配置文件 编辑:程序博客网 时间:2024/06/01 16:39
典型动态规划题目 链接 hdu-1024
题目大概意思是在长度为 i 的序列中找出 j 段连续子序列,并且这 j 段序列元素的和为最大值。
假设S[i]存放的是题目给出的序列,不难发现,总共也只有两种情况:1,若从前 i 段中选 j 段出来最后一段的最后一个元素是 S[i] 的话,若S[i+1]>=0,S[i+1]直接并入最后一段就行,若S[i+1]<0,跳过这一个元素。 2,若最后一个元素不是S[i],则dp[i][j]=max(dp[k][j-1]+maxsum(k+1,i))1<=k<i,意思是从前k个元素中找出j-1段,再在第k+1到第i个元素中找出最后一段序列,这里k需要每一次都要从 1 到 i-1 变化才能保证每次找出最大序列而maxsum(i,j)代表的是找到从第 i 个到第 j 元素间的最大子序列和,最快算法时间复杂度为O(n),对于第一种情况时间复杂度为O(1),第二种情况为O(n^2),加上 i 的迭代,总的时间复杂度将为O(n^3),当然会超。
如果直接常规性的用dp[i][j]这样来存放和计算的话内存和时间都将超出,空间复杂度为O(n^2),而n的范围为[1,100万],内存也会超。
现在引入数组 q,q[j]代表从前 i 个元素中选 j 段出来并且最后一段结尾元素一定为S[i] 的最大值(这个道理和从简单的从n个元素中找1段的算法是一个道理)
再创建数组 p 代替数组dp,p[j]代表从前 i 个元素中选 j 段的最大和,而把 i 放到最外层迭代,和从n个元素中找一段类似。
显然p[j]>=q[j],也就是从前 i 段中选 j 段的最大和。
先直接贴出代码:
#include<iostream>#include<cstring>using namespace std;#define mem(a) memset(a,0,sizeof(a))#define max(a,b) (a>b?a:b)#define min(a,b) (a<b?a:b)#define MaxN 1000050int S[MaxN],p[MaxN],q[MaxN];int main(){ int N,m; while(cin>>m>>N){ for(int i=1;i<=N;i++){ cin>>S[i]; } mem(p);mem(q);//p[j]代表从前i个中选j段的最大值 q[j]代表从前i段中选j段并且一定要有S[i]在内的最大值 p[1]=q[1]=S[1]; for(int i=1;i<=N;i++){ for(int j=min(i,m);j>0;j--){ if(j==i)p[j]=q[j]=p[j-1]+S[i]; else{ q[j]=max(q[j]+S[i],p[j-1]+S[i]); p[j]=max(p[j],q[j]); } } } cout<<p[m]<<endl; }}当最外层的 i-1 增加1变成 i 后,新的循环开始执行,为了方便理解先添加上 i 下标,q[i][j]=max(q[i-1][j]+S[i],p[i-1][j-1]+S[i]),p[i][j]=max(p[i-1][j],q[i][j])。
p[i][j]的值要么为舍弃S[i]后的p[i-1][j]或者不舍弃S[i]从前k个元素中选j-1段再从k+1到 i 中选出最后一段的q[i][j],而q[i][j]要么为直接吧S[i]并入最后一段的q[i-1][j]+S[i]要么为从前k个中选出 j-1 段然后S[i]单独最为一段。
而在每次 i 增加1循环还没开始执行前,q[j],p[j]中存放的是q[i-1][j],p[i-1][j],执行后存放的是q[i][j],p[i][j]。因为每次更新需要用到q[i-1][j],p[i-1][j],所以q[i-1],p[i-1]的更新需要在q[i],p[i]的更新之后。所以上面是倒序更新的。而p[i-1][j],q[i-1][j]在p[i][j],q[i][j]更新之后就没用了,所以直接用p[i-1][j],q[i-1][j]的空间来存放p[i][j],q[i][j]。也就只需要写p[i],q[i]了。
- hdu-1024 多段子段最大和问题
- hdu Max Sum Plus Plus(最大m段子段和)
- hdu Max Sum Plus Plus(最大m段子段和)
- HDU 1024 最大m段子段和 Max Sum Plus Plus
- HDU 1024 Max Sum Plus Plus((最大m段子段和))(动态规划经典)
- hdu1024 最大M段子段和
- hdu1024(m段子段和最大)
- 【u124】环状最大两段子段和
- HDU 1024 m段子段和最大值 (DP)
- P1121 环状最大两段子段和(DP)
- 洛谷 P1121 环状最大两段子段和
- 洛谷1121环状最大两段子段和
- 洛谷 P1121 环状最大两段子段和
- 动态规划 P1121 环状最大两段子段和
- hdu 1024 最大m子段和
- hdu 1024最大m子段和
- hdu 1024 最大M子段和
- hdu 1024 最大M子段和
- (UART 与 USART有什么区别)&(SPI、I2C、UART三种串行总线协议的区别)
- 初探SpringBoot
- 剑指offerT41另外一种解法
- 通过虚拟机搭建缓存集群
- Is Derek lying? HDU
- hdu-1024 多段子段最大和问题
- 第二章 进程管理
- Python: PS 滤镜-- 极坐标变换到平面坐标
- GitHub+node.js+hexo搭建个人博客教程
- Java之Lombok
- 习题7-13:数字表达式
- 1033. 旧键盘打字(20)
- 【c++】检测一个函数运行的时间
- docker入门