【题解】最大 M 子段和 Max Sum Plus Plus [Hdu1024] [51nod1052]
【题解】最大 M 子段和 Max Sum Plus Plus [Hdu1024] [51nod1052]
传送门:最大 \(M\) 子段和 \(Max\) \(Sum\) \(Plus\) \(Plus\) \([Hdu1024]\) \([51nod1052]\)
【题目描述】
给出一个长度为 \(N\) 的序列 ,将这 \(N\) 个数划分为互不相交的 \(M\) 个子段,并使得 \(M\) 个子段的和最大。
【样例】
样例输入:
7 2
-2
11
-4
13
-5
6
-2
样例输出:
26
【数据范围】
\(100\%\) \(1 \leqslant N \leqslant 10^6\)
【分析】
在 \(51nod\) 里面这道题的数据水出了一种极其诡异的境界,首先是它题目里瞎扯的一个特判没毛用,其次,我尝试了不下 \(10\) 种错误写法(包括不同题意所造成的不同写法),居然全对 \(...\)
设 \(dp[i][j]\) 表示使用前 \(j\) 个数划分了 \(i\) 段的最大和。
由于所选段不一定要连续,所以 \(dp[i][j]=dp[i][j-1]\),即第 \(i\) 段不选 \(a[j]\) 的情况。
如果要选 \(a[j]\) ,那么应该是从 \(a[j]\) 往前选出连续的一段 \([k+1,j]\) 作为第 \(i\) 段,即 \(dp[i][j]=max\{dp[i-1][k]+S[j]-S[k]]\}\),其中 \(k \in[i-1,j-1],\) 为了保证这之后剩下的数可以足够选完 \(m\) 段,需要满足 \(i-j \geqslant m-n\) 即 \(j \in [i,n-m+i]\),\(S[i]\)为 \(a[i]\) 的前缀和 。
开一个滚动数组 \(f\) 优化掉第一维,就成了酱紫: \(dp[j]=\begin{cases} max_{k=i-1}^{j-1}\{f[k]-S[k]]\}+S[j] & j=i\\max\{dp[j-1],{max_{k=i-1}^{j-1}\{f[k]-S[k]]\}+S[j]}\} & j>i \end{cases}\)
对于上面 \(j=i\) 的情况,实际操作时,可以特判,也可以直接 \(dp[i-1]=-inf\) 。
后面那一大堆求最大值的表达式可以直接用一个变量 \(maxs\) 来保存,初始值为 \(f[i-1]-S[i-1]\),每求完一个 \(dp[j]\),就让其与 \(f[j]-S[j]\) 取个最大值,下一次 \(dp[j+1]\) 要使用 \(maxs\) 时,其维护的区间信息恰好为 \([i-1,(j+1)-1]\) 。
【Code】
#include<algorithm>
#include<cstring>
#include<cstdio>
#define LL long long
#define Re register LL
using namespace std;
const int N=1e6+3;
LL n,m,tmp,ans,maxs,S[N],f[N],dp[N];
inline void in(Re &x){
int f=0;x=0;char c=getchar();
while(c<'0'||c>'9')f|=c=='-',c=getchar();
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c^48),c=getchar();
x=f?-x:x;
}
int main(){
while(scanf("%lld%lld",&m,&n)!=EOF){
for(Re i=1;i<=n;++i)in(S[i]),tmp+=(S[i]>0),S[i]+=S[i-1];
memset(dp,0,sizeof(dp));
memset(f,0,sizeof(f));
for(Re i=1;i<=m;++i){
for(Re j=1;j<=n;++j)f[j]=dp[j];
maxs=f[i-1]-S[i-1];
dp[i-1]=-1e18;
for(Re j=i;j<=n-m+i;++j){
dp[j]=max(dp[j-1],maxs+S[j]);
maxs=max(maxs,f[j]-S[j]);
}
}
printf("%lld\n",dp[n]);
}
}
【题解】最大 M 子段和 Max Sum Plus Plus [Hdu1024] [51nod1052]的更多相关文章
- 最大子段和(Max Sum)
Max Sum. The following is an instance. a) (-2,11,-4,13,-5,-2) 思路: 最大子段和:给定一个序列(元素可正可负),找出其子序列中元素和 ...
- HDU 1024 Max Sum Plus Plus【动态规划求最大M子段和详解 】
Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- HDOJ-1003 Max Sum(最大连续子段 动态规划)
http://acm.hdu.edu.cn/showproblem.php?pid=1003 给出一个包含n个数字的序列{a1,a2,..,ai,..,an},-1000<=ai<=100 ...
- [ACM] hdu 1003 Max Sum(最大子段和模型)
Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...
- (最大m子段和) Max Sum Plus Plus (Hdu 1024)
http://acm.hdu.edu.cn/showproblem.php?pid=1024 Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/ ...
- HDU 1003:Max Sum(DP,连续子段和)
Max Sum Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Su ...
- HDU 1024:Max Sum Plus Plus(DP,最大m子段和)
Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- HDU 1024 Max Sum Plus Plus(m个子段的最大子段和)
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1024 Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/ ...
- hdu 1024 Max Sum Plus Plus (子段和最大问题)
Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
随机推荐
- 人大金仓KCI
#include "bin/libkci.h" static void exit_nicely(KCIConnection *conn) { KCIConnectionDestor ...
- 字符串的sizeof长度及strlen长度
在C/C++中,字符串是以零('\0')结尾的.比如,对于下面的字符串: "hello" 在最后一个字符'd'后面,还有一个我们肉眼看不见的'\0'字符,作为该字符串的结束符.所 ...
- 用matlab计算线性回归问题
看机器学习的时候遇到的第一个算法就是线性回归,高数中很详细的说明了线性回归的原理和最小2乘法的计算过程,很显然不适合手动计算,好在各种语言都有现成的函数使用,让我们愉快的做个调包侠吧 简单线性回归 R ...
- 常用SQL语句分享
前言: 日常工作或学习过程中,我们可能会经常用到某些SQL,建议大家多多整理记录下这些常用的SQL,这样后续用到会方便很多.笔者在工作及学习过程中也整理了下个人常用的SQL,现在分享给你!可能有些S ...
- python打印带颜色字体
设置颜色开始 :\033[显示方式;前景色;背景色m 前景色 背景色 颜色 30 40 黑色 31 41 红色 32 42 绿色 33 43 黃色 34 44 蓝色 35 45 紫红色 36 46 青 ...
- 机器学习之KMeans聚类
零.学习生成测试数据 from sklearn.datasets import make_blobs from matplotlib import pyplot # create test data ...
- Bash Shell如何实现动态变量
有时需要遍历所有变量,但是如何生成变量名之后,再取到变量名里的值呢? 具体方法 测试动态变量的脚本: #!/bin/bash a=1 b=abc abc1='12345abc' tmp1=$(eval ...
- (原)堆叠hourglass网络
转载请注明出处: https://www.cnblogs.com/darkknightzh/p/11486185.html 论文: https://arxiv.org/abs/1603.06937 官 ...
- Jupyter notebook 中常用的快捷键
1.注释和缩进 注释一行或多行: Ctrl + / 多行同时缩进:Tab 或者 Ctrl + ] 多行取消缩进: Shift + Tab 或者 ctrl + [ 2.编辑和运行 Enter : 转入编 ...
- 高斯混合模型GMM与EM算法的Python实现
GMM与EM算法的Python实现 高斯混合模型(GMM)是一种常用的聚类模型,通常我们利用最大期望算法(EM)对高斯混合模型中的参数进行估计. 1. 高斯混合模型(Gaussian Mixture ...