题意:
告诉你一些数字 ,让你在其中找出两段,使得这两段数字累加的和最大。
Hint:
如给你的数字是 10 1 -1 2 2 3 -3 4 -4 5 -5 则答案是 13。
因为In the sample, we choose {2,2,3,-3,4} and {5}, then we can get the answer.
类型:
DP动态规划
思路:
My思路:(本思路过于奇葩,脑血拴心脏病患者请不要阅读)
把所有的相关的条件都表示成状态,然后写出状态之间转移的方程
所以我本题弄的状态十分恶心。。。
dp[i][j][k]表示从第0个数到第i个数,(j==0?包含:不包含)其本身的(k==0?单区间:双区间)最大值。
其中单区间的意思是从0到i这段上,一个区间的最大和。双区间就是这段上两个区间累加最大和,也就是题目要求内容.
状态转移方程就很好写了,注意细节就好。具体看代码
网查经典思路:
正向求1-i的单区间最大,反向求i-n的单区间最大,然后遍历n,对于每个分割点,其解就是 左边正向最大+右边反向最大。 找出所有分割的最大值就好。
注意点:
初始化时,首先初始化值不能被正常算出,其次,有些不可能的情况(如只含一个元素的双区间最大,问题本身就不成立),要确保他被丢弃。因为这里是求最大值,所以我设置成了很小的值,这样在算max的时候,一定会被丢弃。
代码:
POJ 2479:Maximum sum 算法复杂度:O(4n)
/************************************************************************* > File Name: poj2479.cpp > Author: Shine > Created Time: 2013-05-13 下午 5:25:18 > QuestionType: dp动态规划 > Way: 把所有限制条件写成状态,然后写出状态转移方程 > Submit: 1WA(状态转移方程错误+初始化错误) 1AC > Gain: DP基本写法 > Experience: 交题目之前要测试哦~~ ************************************************************************/ #include <cstdio> #include <cstring> #include <cstdlib> #define INF 99999999 #define max(a,b) ((a)>(b)?(a):(b)) enum {one, two}; enum {isin, notin}; int a[50010]; int dp[50010][2][2]; int dfs(int i, int state, int num) { if (dp[i][state][num] != -INF) return dp[i][state][num]; int &ans = dp[i][state][num]; int t; switch(num) { case one: switch(state) { case isin: ans = max(dfs(i-1,isin,one)+a[i],a[i]); break; case notin: ans = max(dfs(i-1,isin,one), dfs(i-1,notin,one));break; }break; case two: switch(state) { case isin: t = max(dfs(i-1,isin,one), dfs(i-1,notin,one)); ans = max(t, dfs(i-1,isin,two)) + a[i]; break; case notin:ans = max(dfs(i-1,isin,two), dfs(i-1,notin,two)); break; }break; } return ans; } int main() { int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); int i; for (i = 0; i < n; i++) { scanf("%d", &a[i]); } for (i = 0; i < 50005; i++) { int j; for (j = 0; j <= 1; j++) { int k; for (k = 0; k <= 1; k++) { dp[i][j][k] = -INF; } } } dp[0][isin][one] = a[0]; dp[0][notin][one] = -INF+1; dp[0][isin][two] = -INF+1 ; dp[0][notin][two] = -INF+1; dp[1][isin][one] = max(a[0]+a[1], a[1]); dp[1][notin][one] = a[0]; dp[1][isin][two] = a[0]+a[1]; dp[1][notin][two] = -INF+1; dp[2][notin][two] = a[0]+a[1]; dfs(n-1, isin, two); dfs(n-1, notin, two); printf("%d\n", max(dp[n-1][isin][two], dp[n-1][notin][two])); } return 0; }