POJ 2479:Maximum sum

题意:

告诉你一些数字 ,让你在其中找出两段,使得这两段数字累加的和最大。

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;
}

 

 

posted on 2013-05-13 18:38  ShineCheng  阅读(136)  评论(0编辑  收藏  举报

导航