POJ 2479 (动态规划)

来源:互联网 发布:php微信wap支付 demo 编辑:程序博客网 时间:2024/06/12 20:37

作为比较经典的算法思想,动态规划恐怕早已深入人心。今天在网上找了一个 题目来练练手。

题目大意:

给出一个 数字序列,求出最大的两个不连续子串之和 。 

这道题 看似 就是 最大子序列和 的一个变种。本质都是用 DP 来解决。

首先,将 a[i] 表示第 i 个元素,再建立 三个数组 tm[num],sm[num],stm[num]

含义如下: tm[i] 表示 以第i个元素结尾的最大字串;sm[i] 表示以第i个元素开头的最大字串;

最后一个stm比较关键,stm[i] 表示后面 n-i+1 个元素的最大值

这里举个例子:

-1,2,3,4,2,5

一个6个元素,stm[2]表示后面5个元素的最大子串的值(6-2+1)

那么,下面就可以列出状态转移方程:

tm[i] = max{ tm[i-1]+a[i],a[i]}

sm[i] = max{sm[i+1]+a[i],a[i]}

stm[i] = max{stm[i+1],sm[i]}    这个方程的意思是,后面x个数的最大字串的值 = max(后面x-1个数的最大子串的值,以第i个元素开头的最大子串}

说明:状态转移方程只要合理,能解释得清楚,即符合题意。 方程不唯一。

////  main.cpp//  Demo////  Created by Jaster_chen on 1/27/16.//  Copyright © 2016 Jaster_chen. All rights reserved.//#include <iostream>using namespace std;#define MAX 50001#define max(a,b) a>b?a:bint a[MAX],tm[MAX],sm[MAX],stm[MAX];//tm表示以i为结尾的最大字串,sm表示以i开始的最大字串,stm[i]表示取后面 num-i+1 个元素最大值int main(){    int T,num,i;    scanf("%d",&T);    while(T--){        cin>>num;        for(i=1;i<=num;i++){            scanf("%d",&a[i]);        }        tm[1] = a[1];        for(i=2;i<=num;i++){            tm[i] = max(tm[i-1]+a[i],a[i]);        }        sm[num] = a[num];        for(i=num-1;i>=1;i--){            sm[i] = max(sm[i+1]+a[i],a[i]);        }        stm[num] = a[num];        for(i=num-1;i>=1;i--){            stm[i] = max(stm[i+1],sm[i]);        }        int sum;        sum = tm[1]+stm[2];        for(i=2;i<=num-1;i++){            sum = max(sum,tm[i]+stm[i+1]);        }        printf("%d\n",sum);    }    return 0;}

代码写完之后,时间复杂度保持在 O(n),但是 在POJ上 总是通不过,说是 时间超时。

检查了好几遍,发现没问题。

终于发现是 因为 cin,cout,用scanf,printf代替就行。

所以,做 POJ,HDU,ACM的题目还是 用 scanf,printf 时间 快一点。

0 0
原创粉丝点击