题意:给一个数列,求任意两个子序列的包含元素的和的最大值,两个子序列无公共部分。
思路:
dp1[i]表示第一个元素a[1]到a[i]的最大子段和,状态转移方程是dp1[i] = max(dp1[i-1]+a[i],a[i]);//不理解最大子段和方程的可以参考最大子段和问题
dp2[i]表示末一个元素a[n]到a[i]的最大子段和,状态转移方程是dp2[i] = max(dp2[i+1]+a[i],a[i]);
再用ans1[i]表示max{dp1[1],dp1[2],...,dp1[i]},用ans2[i]表示max{dp2[n],dp2[n-1],...,dp2[i]},
dp1[i]表示以第i个数结尾的区间最大和,ans1[i]表示到第i个数为止的最大区间和(不一定以第i个数结尾
ans1[i]+ans2[i+1]即表示分割点i左边最大区间和与右边最大区间和之和//我才没晕呢TT
再枚举分割点即可。
code:
/*
*Author : novicer
*Created Time : 2015-07-21 18:37:25
*File name : poj2479.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
const int inf = 1000000;
typedef long long lint;
#define cls(a) memset(a,0,sizeof(a))
#define rise(i,a,b) for(int i = a ; i <= b ; i++)
#define fall(i,a,b) for(int i = a ; i >= b ; i--)
const int maxn = 50000 * 2 + 5;
int a[maxn];
int dp1[maxn];
int dp2[maxn];
int ans1[maxn];
int ans2[maxn];
int t;
void solve(){
int t;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
cls(a);cls(dp1);cls(dp2);cls(ans1);cls(ans2);
for(int i = 1 ; i <= n ; i++) scanf("%d",&a[i]);
dp1[1] = a[1];
for(int i = 2 ; i <= n ; i++) dp1[i] = max(dp1[i-1]+a[i] , a[i]);
ans1[1] = a[1];
for(int i = 2 ; i <= n ; i++) ans1[i] = max(ans1[i-1] , dp1[i]);
dp2[n] = a[n];
for(int i = n -1 ; i >= 1 ; i--) dp2[i] = max(dp2[i+1]+a[i] , a[i]);
ans2[n] = a[n];
for(int i = n -1 ; i >= 1 ; i--) ans2[i] = max(ans2[i+1] , dp2[i]);
int ans = -inf;
for(int i = 1 ; i <= n - 1 ; i++) ans = max(ans , ans1[i]+ans2[i+1]);
printf("%d\n",ans);
}
}
int main(){
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
solve();
return 0;
}
题意:同上题,格式范围略有改动。
思路:做完上一题顺手A了它吧:)
code:
/*
*Author : novicer
*Created Time : 2015-07-21 19:37:25
*File name : poj2593.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<iomanip>
using namespace std;
const double eps(1e-8);
const int inf = 1000000;
typedef long long lint;
#define cls(a) memset(a,0,sizeof(a))
#define rise(i,a,b) for(int i = a ; i <= b ; i++)
#define fall(i,a,b) for(int i = a ; i >= b ; i--)
const int maxn = 1000000 * 2 + 5;
int a[maxn];
int dp1[maxn];
int dp2[maxn];
int ans1[maxn];
int ans2[maxn];
int n;
void solve(){
while(scanf("%d",&n)&&n){
cls(a);cls(dp1);cls(dp2);cls(ans1);cls(ans2);
for(int i = 1 ; i <= n ; i++) scanf("%d",&a[i]);
dp1[1] = a[1];
for(int i = 2 ; i <= n ; i++) dp1[i] = max(dp1[i-1]+a[i] , a[i]);
ans1[1] = a[1];
for(int i = 2 ; i <= n ; i++) ans1[i] = max(ans1[i-1] , dp1[i]);
dp2[n] = a[n];
for(int i = n -1 ; i >= 1 ; i--) dp2[i] = max(dp2[i+1]+a[i] , a[i]);
ans2[n] = a[n];
for(int i = n -1 ; i >= 1 ; i--) ans2[i] = max(ans2[i+1] , dp2[i]);
int ans = -inf;
for(int i = 1 ; i <= n - 1 ; i++) ans = max(ans , ans1[i]+ans2[i+1]);
printf("%d\n",ans);
}
}
int main(){
// freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
solve();
return 0;
}