大家觉得写还可以,可以点赞、收藏、关注一下吧!
也可以到我的个人博客参观一下,估计近几年都会一直更新!和我做个朋友吧!https://motongxue.cn
洛谷 T147555 赚钱
题目描述
在遥远的X星生活着一群X星人,他们每天都要去赚钱维持生计。他们赚钱的方式和我们不同,他们把捡钱当成赚钱。而且他们的钱有正数也有负数,谁都不希望自己拿到太多的负数钱。他们每天工作的地点都不同,今天,小x来到了一个新地方,这里打横排列着一些钱(数量为n),每张钱的面值可能相同,也可能不同。X星捡钱的规则如下:你不能打乱这些钱的顺序,你只能拿两个连续的区间的钱,且这两个连续的区间不能重叠。你能否帮助小x拿到更多的钱?
PS:选中的两堆钱中,你都必须至少选择一张。
输入格式
第一行为正整数n。 第二行为n个整数 a i a_i ai,按顺序对应每一张钱的面值。
输出格式
输出能够赚到的最多的钱。
样例
输入 #1复制
6
1 3 -1 2 -1 2
输出 #1复制
7
说明/提示
2 < = n < = 1 e 5 2<=n<=1e5 2<=n<=1e5
− 1 e 4 < = a i < = 1 e 4 -1e4<= a_i <=1e4 −1e4<=ai<=1e4
分析
这是一道典型的动态规划题,原题是最大连续子序列和,一开始的思路是分段求最大连续子序列和,结果超时了,直接0分
后来思路不变,不过先把数据存进数组里面,保证时间复杂度为
O
(
n
)
O(n)
O(n)
- 先求出序列从后边到前面的最大连续子序列和
funFromEnd()
- 在求从前到后的最大连续子序列和
funFromStart
时,得出前面每一段的最大连续和 - 查询过程中,直接从
end
数组中找出后面一段的最大连续和,得出finalRes
- 再对每一次
finalRes
取最大值finalRes = Math.max(MaxSum + c[j + 1], finalRes);
,就可得到最终答案了
代码
/*
* @Author: motongxue
* @Date: 2020-09-16 16:19:25
* @LastEditors: motongxue
* @LastEditTime: 2020-09-20 10:37:19
* @Blog: https://motongxue.cn
* @Description: file content
*/
import java.util.Scanner;
public class Main {
static Long[] a, end;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
a = new Long[n];
end = new Long[n];
for (int i = 0; i < a.length; i++) {
a[i] = sc.nextLong();
}
funcFromEnd(n);
System.out.println(funcFromStart(n));
}
public static Long funcFromStart(int N) {
Long ThisSum, MaxSum;
int j;
ThisSum = MaxSum = 0L;
Long finalRes = 0L;
for (j = 0; j < N - 1; j++) {
ThisSum += a[j];
MaxSum = Math.max(ThisSum, MaxSum);
finalRes = Math.max(MaxSum + end[j + 1], finalRes);
if (ThisSum < 0)
ThisSum = 0L;
}
return finalRes;
}
public static void funcFromEnd(int N) {
Long ThisSum, MaxSum;
int j;
ThisSum = MaxSum = 0L;
for (j = N - 1; j >= 0; j--) {
ThisSum += a[j];
MaxSum = Math.max(ThisSum, MaxSum);
end[j] = MaxSum;
if (ThisSum < 0)
ThisSum = 0L;
}
}
}
提交结果
泪目
2020年9月20日更
大家觉得写还可以,可以点赞、收藏、关注一下吧!
也可以到我的个人博客参观一下,估计近几年都会一直更新!和我做个朋友吧!https://motongxue.cn