洛谷 T147555 赚钱 动态规划

大家觉得写还可以,可以点赞、收藏、关注一下吧!
也可以到我的个人博客参观一下,估计近几年都会一直更新!和我做个朋友吧!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)

  1. 先求出序列从后边到前面的最大连续子序列和funFromEnd()
  2. 在求从前到后的最大连续子序列和funFromStart时,得出前面每一段的最大连续和
  3. 查询过程中,直接从end数组中找出后面一段的最大连续和,得出finalRes
  4. 再对每一次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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值