【书上讲解】最大m段子段和问题
描述
【题解】
设f[i][j]表示前i个数字分成了j段的最大子段和。
则f[i][j] = max(f[i-1][j]+a[i] (第i个数字和第j段合在一起),f[k][j-1]+a[i] (第i个数字作为第j段的第一个数字,同时在j-1段的情况中找到和最大的那个))
这样的时间复杂度是$O(m*n^2)$的,代码的写法在代码1中
接下来我们做一些优化。
首先把数组的第二维改成滚动数组。
然后令F[i][j]=max(f[1..i][j]);
这样在做第二层的转移的时候f[i][j]就能直接用F[i-1][j-1]做转移了
当然也不用非得再重开一个新的数组。
在f[i][j]做完转移之后把它改成前缀的最大值就行。(注意一定要做完转移之后再改变,因为f[i][j]在转移的时候用到了f[i-1][j])
这样在做转移的时候就少掉了O(N)的一次枚举了
复杂度变成O(n*m)的了.详见代码2
【代码1】
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 1e6;
const int M = 30;
int f[N+10][M+10],a[N+10];
int n,m;
int main(){
while (~scanf("%d%d",&m,&n)){
for (int i = 1;i <=n;i++) scanf("%d",&a[i]);
for(int l = 1;l <= m;l++){
for (int i = l;i <= n;i++){
if (i==l){
f[i][l] = f[i-1][l-1]+a[i];
}else{
f[i][l] = f[i-1][l]+a[i];//和第l段合并
//printf("%d ",f[i][l]);
//自己独立成段
for (int k = l-1;k <= i-1;k++)
f[i][l] = max(f[i][l],f[k][l-1]+a[i]);
}
}
}
int ans = f[m][m];
for (int i = m+1;i <= n;i++) ans = max(ans,f[i][m]);
printf("%d\n",ans);
}
return 0;
}
【代码2】
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e6;
const int M = 30;
int f[N+10][2],a[N+10];
int n,m;
int main(){
while (~scanf("%d%d",&m,&n)){
for (int i = 1;i <=n;i++) scanf("%d",&a[i]);
memset(f,0,sizeof f);
for(int l = 1;l <= m;l++){
for (int i = l;i <= n;i++){
if (i==l){
f[i][l&1] = f[i-1][(l-1)&1]+a[i];
}else{
f[i][l&1] = f[i-1][l&1]+a[i];//和第l段合并
//printf("%d ",f[i][l]);
//自己独立成段
f[i][l&1] = max(f[i][l&1],f[i-1][(l-1)&1]+a[i]);
}
}
for (int i = l+1;i <= n;i++)
f[i][l&1] = max(f[i][l&1],f[i-1][l&1]);
}
printf("%d\n",f[n][m&1]);
}
return 0;
}
【书上讲解】最大m段子段和问题的更多相关文章
- JAVA理解逻辑程序的书上全部重要的习题
今天随便翻翻看以前学过JAVA理解逻辑程序的书上全部练习,为了一些刚学的学弟学妹,所以呢就把这些作为共享了. 希望对初学的学弟学妹有所帮助! 例子:升级“我行我素购物管理系统”,实现购物结算功能 代码 ...
- 洛谷P1121 环状最大两段子段和
题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的第一行是一个正整数N,表示了序列 ...
- 洛谷 P1121 环状最大两段子段和 解题报告
P1121 环状最大两段子段和 题目描述 给出一段环状序列,即认为\(A_1\)和\(A_N\)是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 第一行是一个正整数 ...
- P1121 环状最大两段子段和
P1121 环状最大两段子段和 题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的 ...
- 【u124】环状最大两段子段和
Time Limit: 1 second Memory Limit: 128 MB [问题描述] 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. ...
- java核心编程书上的一个错误
书上说这段代码说明了java对对象不是采用的按引用调用 这明显错了,java还是引用传递,只是把引用对象的变量复制了,互换了x,y所指的对象,对a,b没有影响
- 最大m段子段和 Day9 - E - Max Sum Plus Plus HDU - 1024
Now I think you have got an AC in Ignatius.L's "Max Sum" problem. To be a brave ACMer, we ...
- c++编程思想(四)--对象和隐藏(感觉书上有误)
c++编程思想里数据抽象和隐藏实现实际就是通常所说的类和封装: 封装,继承,多态对象特点说的很多,就不再说了 关于封装,本人觉得书上有个地方写的有问题,p145和p153都提到Y::f(X*)引用了X ...
- OK 开始实践书上的项目一:即使标记
OK 开始实践书上的项目一:及时标记 然而....又得往前面看啦! ----------------------我是分割线------------------------ 代码改变世界
随机推荐
- iSkysoft iMedia Converter Deluxe Mac如何制作视频?视频格式转换工具制作动图的方法
使用iSkysoft iMedia Converter Deluxe Mac如何制作视频?使用视频格式转换工具,你可以轻松进行动图或视频的制作,也可以把你喜欢的视频的某一段提取出来,制作成你自己风格的 ...
- Spring data jpa 依赖配置
<properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> &l ...
- Mavlink_main.cpp源码学习
int mavlink_main(int argc, char *argv[]) { if (argc < 2) { usage(); ...
- 【Java架构:基础技术】一篇文章搞掂:Gradle
前言 Gradle是什么: Gradle提供了一个域特定语言(DSL),用于描述构建 它使用 Groovy 语言,使其更容易来形容和构建 Gradle 中的每一个构建脚本使用UTF-8进行编码保存,并 ...
- (转)Android Studio解决unspecified on project app resolves to an APK archive which is not supported
出现该问题unspecified on project app resolves to an APK archive which is not supported as a compilation d ...
- Python selenium web UI之Chrome 与 Chromedriver对应版本映射表及下载地址和配置(windows, Mac OS)
浏览器及驱动下载 进行web UI 自动化时,需要安装浏览器驱动webdriver,Chrome浏览器需要安装chromedriver.exe 驱动,Firefox需安装 geckodriver.ex ...
- Ngrinder简单使用
文章目录 安装 试玩 性能测试 安装 https://github.com/naver/ngrinder/releases 下载对应版本,是一个war包,3.4以上支持jdk1.8 将war包放到to ...
- OA集成备注
1. 查看轨迹方法<script type="text/javascript"> function WinOpenIt(url) { //alert(1); var t ...
- python 自带http服务
python2: python -m SimpleHTTPServer python3: python3 -m http.server
- Python系列——常用第三方库
幕布视图(更加方便.明了):https://mubu.com/doc/AqoVZ8x6m0 参考文献:嵩天老师的Python讲义 模块 定义 计算机在开发过程中,代码越写越多,也就越难以维护,所以为了 ...