炸弹

69 篇文章 0 订阅

炸弹


问题描述

高老大又在鼓捣炸弹了,这不,启动了一个了。
英明英勇的老大又在跟他的部下们表演空手光速拆炸弹了。
炸弹上是一个圆盘,圆盘上顺时针写着 N 个数。
其实这个炸弹就是要求从中选择若干个连续的数(注意每个数最多只能选一次)加起来,使得这些数字的和最大,然后输入这个最大的和,计时就会停止。
现在你被老大要求上台表演,时间是 1s,任务就交给你了。


输入

输入文件名为Bomb.in。
输入第一行包含一个正整数 N ,表示数字的个数。
第二行包含 N 个整数,为所给的数字。


输出

输出文件名为Bomb.out。
输出包含一个整数,为最大的可以得到的和。


输入样例

8
2 -4 6 -1 -4 8 -1 3


输出样例

14


数据范围

对于 30% 的数据 1<=N<=200 ;
对于 70% 的数据 1<=N<=10000 ;
对于 100% 的数据 1<=N<=100000 , 答案在longint范围内。


Solution

首先,我们假设这不是一个环。
n 处把它断开。
然后就是 O(n) 求最大连续子序列。
环的情况怎么处理呢?
我们将一个方案分成两部分,一部分从 1 开始递增,一部分从 n 开始递减。
然后用动归就可以求出末端不超过 i 且从 1 n <script type="math/tex" id="MathJax-Element-518">n</script> 出发的最大连续子序列。


Code

#include <iostream>
#include <cstdio>

#define Max(x,y) ((x)>(y)?(x):(y))

using namespace std;

int n,ans;

int w[100010];

int f[100010];

int f1[100010];
int f2[100010];

int s1[100010];
int s2[100010];

int main(){

    freopen("bomb.in","r",stdin);

    freopen("bomb.out","w",stdout);

    scanf("%d",&n);

    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);

    for(int i=1;i<=n;i++){

        f[i]=Max(f[i-1]+w[i],w[i]);

        s2[i]=s2[i-1]+w[i];

        f2[i]=Max(f2[i-1],s2[i]);

        ans=Max(ans,f[i]);

    }

    for(int i=n;i>=1;i--){

        s1[i]=s1[i+1]+w[i];

        f1[i]=Max(f1[i+1],s1[i]);

        ans=Max(ans,f2[i-1]+f1[i]);

    }

    printf("%d\n",ans);

    return 0;

}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值