当前位置: 代码迷 >> 综合 >> NYOJ - 745 - 蚂蚁的难题(二)(最大子序列和变形,动态规划)
  详细解决方案

NYOJ - 745 - 蚂蚁的难题(二)(最大子序列和变形,动态规划)

热度:83   发布时间:2023-10-09 17:31:35.0
描述

下雨了,下雨了,蚂蚁搬家了。

已知有n种食材需要搬走,这些食材从1到n依次排成了一个圈。小蚂蚁对每种食材都有一个喜爱程度值Vi,当然,如果Vi小于0的时候,表示蚂蚁讨厌这种食材。因为马上就要下雨了,所以蚂蚁只能搬一次,但是能够搬走连续一段的食材。时间紧急,你快帮帮小蚂蚁吧,让它搬走的食材喜爱值和最大。

输入
有多组测试数据(以EOF结尾)。
每组数据有两行,第一行有一个n,表示有n种食材排成了一个圈。(1 <= n<= 50000)
第二行分别有n个数,代表蚂蚁对第n种食材的喜爱值Vi。(-10^9 <= Vi <= 10^9)
输出
输出小蚂蚁能够搬走的食材的喜爱值总和的最大。
样例输入
3
3 -1 2
5
-8 5 -1 3 -9
样例输出
5
7

 

看完题目,很容易联想到最大子串和,只不是这个序列是环形的。现在给出n个数的序列,我们把第一个元素和最后一个元素定义为环相接的地方。

相接的地方的情况有四种情况

1.第一个元素是正数,最后一个元素是正数

2.第一个元素是正数,最后一个元素是负数

3.第一个元素是负数,最后一个元素是正数

4.第一个元素是负数,最后一个元素是负数

我们定义min_sum最小和的子串 max_sum是最大和的子串,sum是n和元素的和

那么,我们要求的ans =max(max_sum,sum-min_sum);

易知最大子序列和中是不包含最小子序列和的,所以,最大子序列和是不横跨连接处的最大和。那么总和sum-最小和min_sum就是横跨连接处的最大和。我们要求的最大和就是在这两个数中找到较大的那一个。


注意:数据范围

#include<cstdio>
#include<cstring>
#include<algorithm>
#define N  50000+1
#define LL long long
using namespace std;
LL v[N],dp1[N],dp2[N];
LL n,max_sum,min_sum,sum;
int main(){while(scanf("%lld",&n)!=EOF){//初始化数组 memset(dp1,0,sizeof(dp1));memset(dp2,0,sizeof(dp2));sum=0;for(int i=1 ;i<=n ;i++){scanf("%lld",&v[i]);sum+=v[i];//元素总和 dp1[i] = max(dp1[i-1]+v[i],v[i]);dp2[i] = min(dp2[i-1]+v[i],v[i]);}max_sum=-9999999;min_sum=9999999;//求最大和与最小和 for(int i=1 ;i<=n ;i++){max_sum = max(max_sum,dp1[i]);min_sum = min(min_sum,dp2[i]);}LL ans = max(max_sum,sum-min_sum);printf("%lld\n",ans);}return 0;
}

??

  相关解决方案