POJ 2479 (连续两个不相交子串和)

本文探讨如何高效地计算给定整数序列中两个不相交子串的最大和,通过介绍动态规划方法,对比超时和优化后的代码实现,以及关键步骤的解释。适合理解子串和问题及动态规划在求解此类问题中的应用。

连续两个不相交子串和

Maximum sum
Description

Given a set of n integers: A={a1, a2,…, an}, we define a function d(A) as below:

Your task is to calculate d(A).
Input

The input consists of T(<=30) test cases. The number of test cases (T) is given in the first line of the input.
Each test case contains two lines. The first line is an integer n(2<=n<=50000). The second line contains n integers: a1, a2, …, an. (|ai| <= 10000).There is an empty line after each case.
Output

Print exactly one line for each test case. The line should contain the integer d(A).
Sample Input

1

10
1 -1 2 2 3 -3 4 -4 5 -5
Sample Output

13
Hint

In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer.

Huge input,scanf is recommended.

题意 :
给定一个序列求出该序列两个不相交子串的最大和

思路 :
两个数组,DP[i][0],DP[i][1];
DP[i][0]表示的是从0~i中连续子串的最大和
DP[i][1]表示i~n-1中连续子串的最大和
则题目就变成求max{DP[i][0]+DP[i+1][1]}
和一个序列子串和最大有区别,我们需要一直维持最大值,然后在一个循环里解决
超时代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn = 5e4 + 5;
typedef long long ll;
ll a[maxn];
ll dp[maxn][2];

int main(){
	int t;cin >> t;
	while(t --){
		int n;cin >> n;
		for(int i = 0;i < n;i ++){
			cin >> a[i];
			if( i )
				dp[i][0] = max(dp[i - 1][0] + a[i],a[i]);
			else
				dp[i][0] = a[i];
		}
		for(int i = n - 1;i >= 1;i --){
			if( i != n - 1)
				dp[i][1] = max(dp[i + 1][1] + a[i],a[i]);
			else
				dp[i][1] = a[i];
		}
		ll ans = -1e18;
		for(int j = 0;j < n - 1;j ++)
			for(int i = j + 1;i < n ;i ++){
				ans = max(ans,dp[j][0] + dp[i][1]);
			}
		cout << ans << endl;
	}
	return 0;
}

AC代码

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;

const int maxn = 5e4 + 5;
int a[maxn];
int dp[maxn][2];

int main(){
	int t;scanf("%d",&t);;
	while(t --){
		int n;scanf("%d",&n);
		int sum = 0;
		for(int i = 0;i < n;i ++){
			scanf ("%d", &a[i]) ;
			if( i ){
				sum = max(sum + a[i], a[i]);
				dp[i][0]=max(sum,dp[i-1][0]);
			}
			else
				dp[i][0] = sum = a[i];
		}
		for(int i = n - 1;i >= 0 ;i --){
			if( i != n - 1){
				sum = max(sum + a[i], a[i]);
				dp[i][1]=max(sum,dp[i+1][1]);
			}
			else
				dp[i][1] = sum = a[i];
		}
		int ans = -(1<<30);
		for(int i = 0;i < n - 1;i ++){
			ans = max(ans,dp[i][0] + dp[i + 1][1]);
		}
		printf("%d\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值