最大m段子段和 Day9 - E - Max Sum Plus Plus HDU - 1024
Given a consecutive number sequence S 1, S 2, S 3, S 4 ... S x, ... S n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ S x ≤ 32767). We define a function sum(i, j) = S i + ... + S j (1 ≤ i ≤ j ≤ n).
Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i 1, j 1) + sum(i 2, j 2) + sum(i 3, j 3) + ... + sum(i m, j m) maximal (i x ≤ i y ≤ j x or i x ≤ j y ≤ j x is not allowed).
But I`m lazy, I don't want to write a special-judge module, so you don't have to output m pairs of i and j, just output the maximal summation of sum(i x, j x)(1 ≤ x ≤ m) instead. ^_^
InputEach test case will begin with two integers m and n, followed by n integers S 1, S 2, S 3 ... S n.
Process to the end of file.
OutputOutput the maximal summation described above in one line.
Sample Input
1 3 1 2 3
2 6 -1 4 -2 3 -2 3
Sample Output
6
8
Hint
Huge input, scanf and dynamic programming is recommended. 思路:最大m段子段和问题,设sum[n][m]为前n个数,m段子段和的最大值,状态转移有三:
1.a[n]不属于该第m段最大和,sum[n][m] = sum[n-1][m]
2.a[n]属于该第m段最大和,且为新的一段 sum[n][m] = sum[n-1][m-1] + a[n]
3.a[n]属于该第m段最大和,且不为新的一段 sum[n][m] = sum[n-1][m] + a[n]
由状态转移方程易知,1与3互相矛盾,就要寻找第二个状态转移方程来辅助计算,令b[n][m]为包含a[n]的前n个数的m段最大子段和,则sum[n][m]为前n个数的m段最大子段和,a[n]不一定包含在内,据此知,sum[n][m] = max(b[j][m])(m<=j<=n),最终答案就是sum[n][m]
由上述分析,可得出b[n][m]的状态转移方程,a[n]属于第m段/不属于第m段,即b[n][m] = max(b[n-1][m], sum[n-1][m-1]) + a[n],通过该式可以得出计算顺序,先计算b[n][m],其中需要sum[n-1][m-1]与b[n-1][m],再更新sum[n][m]),而在计算sum[n][m] = max(b[j][m])(n<=j<=m),类比完全背包的优化,在计算sum[n][m]时,sum[n][m] = max(b[j][m])(m<=j<=n) = max(b[n][m], sum[n-1][m]),因为sum[n-1][m] = max(b[x][m])(m<=x<=n-1),等式成立,我们枚举的顺序是从小到大,所以在sum[n][m]计算之前sum[n-1][m]已经计算好了,不需要再重复枚举了
const int maxm = ; int sum[maxm][maxm], b[maxm][maxm], a[maxm]; int main() {
ios::sync_with_stdio(false), cin.tie();
int n, m;
int tmp;
while(cin >> m >> n) {
memset(sum, , sizeof(sum)), memset(a, , sizeof(a)), memset(b, , sizeof(b));
for(int i = ; i <= n; ++i) cin >> a[i];
for(int i = ; i <= m; ++i) {
for(int j = i; j <= n; ++j) {
b[j][i] = max(b[j-][i], sum[j-][i-]) + a[j];
sum[j][i] = max(sum[j-][i], b[j][i]);
}
}
cout << sum[n][m] << endl;
}
return ;
}
但是注意,该题的范围是1e6,二维显然空间炸了,就需要优化为一维的滚动数组形式,我们将计算的式子都列出来:
b[n][m] = max(b[n-1][m], sum[n-1][m-1]) + a[n], sum[n][m] = max(sum[n-1][m], b[n][m])
滚动时从小到大,该位置为j,则j之前的是[][m],j之后的是[][m-1](上一轮的),则先计算b[],再更新sum[],因为sum和b有冲突,先sum[n-1][m-1],再sum[n-1][m],就用一个tmp来记录
const int maxm = 1e6+; int sum[maxm], b[maxm], a[maxm]; int main() {
ios::sync_with_stdio(false), cin.tie();
int n, m;
int tmp;
while(cin >> m >> n) {
memset(sum, , sizeof(sum)), memset(a, , sizeof(a)), memset(b, , sizeof(b));
for(int i = ; i <= n; ++i) cin >> a[i];
for(int i = ; i <= m; ++i) {
tmp = -0x3f3f3f3f;
for(int j = i; j <= n; ++j) {
b[j] = max(b[j-], sum[j-]) + a[j]; // 此处sum[j-1] 是第i-1段
sum[j-] = tmp; // 更新sum[j-1] 为第i段的, 该tmp是第i段的j-1,由上一次的循环继承而来
tmp = max(sum[j-], b[j]); // 更新tmp, 该tmp是第i段的j,为下一次循环中的的j-1
}
sum[n] = tmp;
}
cout << sum[n] << "\n";
}
return ;
}
参考微博:https://www.cnblogs.com/chuckcpc/p/dp_Max_M_Sum.html
最大m段子段和 Day9 - E - Max Sum Plus Plus HDU - 1024的更多相关文章
- Max Sum Plus Plus HDU - 1024
Max Sum Plus Plus HDU - 1024 Now I think you have got an AC in Ignatius.L's "Max Sum" ...
- C - Max Sum Plus Plus HDU - 1024
用二位数组dp[i][j]记录组数为i,前j个数字的最大子段和. 转移方程: dp[i][j],考虑第j个数,第j个数可以并到前面那一组,此时dp[i][j]=dp[i][j-1]+arr[j],第j ...
- Max Sum Plus Plus HDU - 1024 基础dp 二维变一维的过程,有点难想
/* dp[i][j]=max(dp[i][j-1]+a[j],max(dp[i-1][k])+a[j]) (0<k<j) dp[i][j-1]+a[j]表示的是前j-1分成i组,第j个必 ...
- 洛谷P1121 环状最大两段子段和
题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的第一行是一个正整数N,表示了序列 ...
- 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 ...
- 洛谷 P1121 环状最大两段子段和 解题报告
P1121 环状最大两段子段和 题目描述 给出一段环状序列,即认为\(A_1\)和\(A_N\)是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 第一行是一个正整数 ...
- (最大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 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 ...
随机推荐
- C++中的参数类型
C++中的参数类型 数组 数组是相同类型数据的集合.引入数组就不需要在程序中定义大量的变量,大大减少程序中变量的数量,使程序精炼,而且数组含义清楚,使用方便,明确地反映了数据间的联系.许多好的算法都与 ...
- python 删除git Jenkinsfile文件
背景:在做ci集成的发现分支超过100个之后,pipline activity列表中前期的分支会被隐藏,这导致master分支在活动视图中不可见 解决方案:删除历史分支的Jenkinsfile 分支太 ...
- layer iframe 设置关闭按钮 和刷新和弹出框设置
layer弹出层的关闭问题 就是在执行添加或修改的时候,需要将数据提交到后台进行处理,这时候添加成功之后最理想的状态是关闭弹出层并且刷新列表的数据信息,之前一直想实现这样,可一直没有成功,今天决定 ...
- 快速将Navicat中数据表信息导出
1.使用navicat工具 2.新建查询 SELECT COLUMN_NAME 字段名, COLUMN_TYPE 数据类型, DATA_TYPE 字段类型, CHARACTER_MAXIMUM_L ...
- Android 开发 微信分享,登陆,获取信息
1 获取appid和appsecret. https://open.weixin.qq.com/cgi-bin/index?t=home/index&lang=zh_CN ...
- Linux安装MATLAB2016a
一.准备工具 matlab2016a的镜像文件和破解文件(链接: https://pan.baidu.com/s/1cxtlOM 密码: cj2u) Linux系统,我用的是deepin15.4,和一 ...
- crowdfunding项目01——感人的错误
四十搭环境,半个小时下载jar包,网速感人,一个半小时找bug真是感动 首先SSM项目,主要功能进行增删改查 建立父工程和子工程,产生依赖关系 父工程:pom 子工程:jar.war(web工程) 错 ...
- Java+Selenium+Testng自动化测试学习(四)— 报告
自动化测试报告,在测试用例完成之后系统自动生成HTML报告 使用testng中的报告模板生成报告, 1.在TestSuit.xml文件中配置报告监听 2.运行xml文件 3.自动生成一个test-ou ...
- php 扩展引入
继承引入参数 <?php class A { private $name; private $age; private $time; public function __construct($n ...
- kali&BT5下利用nmap对mysql等数据库渗透与爆破
如今Nmap的脚本引擎从一个普通的端口扫描器转变为具有攻击性的渗透测试工具 .随着nmap各种脚本的存在.到目前为止,我们甚至可以进行完整的SQL数据库渗透而不需要任何其他的工具. 今天就在kali下 ...