[HDU] 1087 Super Jumping! Jumping! Jumping! -基本模型中的 最大递增非连续字段和

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1087

方法:设F(ni)为当第ni个作为一个递增非连续字段最后一个元素的时候,该字段累加的最大值,设第x个元素的值为v(x)。然后建立状态转移方程:

F(ni) = max({F(ai)+v(ni) |  v(ai)<v(ni) and 0<=ai<ni}) ,对每一个这样的第ni个元素做这样的处理,最后的解为:

max( F(x) | 0<=x<=n).

代码实现的时候会有一个优化,那就是对于这样的情况:

1  2  3  4  5  9  8

考虑那个8的时候,是从9往前探寻所有小于8的数,然后用所有 以这些数作为字段结尾的字段和加上8来比较,取最大的作为以8作为字段末尾的字段最大和,找到5是往前找到的第一个小于8的数,得到一个8作为字段末尾的字段最大和的预估值,然后就不需要在去考虑5前面的那些1 2 3 4了,因为他们肯定比不过5.

所以对每一个数都要记录一个东西, 那就是其往直接前面走连续不断的一个递减序列长度l,这样把一个数考虑后,就不用直接去一个一个考虑前面的,而是直接往前跳l个位子,开始新的一个考虑。

比如数据:

x y z a b c d 1  2  3  4  5  9  8

考虑8作为字段末尾的字段最大和的时候,向前探寻到5的时候,取得一个最大和估值,然后不用再考虑5前面的那些1 2 3 4,而是直接跳到 d那个位置。

感谢:优化后速度还是没有起来,不知道为什么。

代码:

View Code
#include<iostream>
#include<math.h>
#include<algorithm>
using namespace std;
int const MAX =0x3f3f3f3f;

int main()
{
    int n;
    while(scanf("%d",&n) && n!=0 )
    {
        int nums[1001];
        int dp[1001];
        int lessCount[1001];
        memset(lessCount,0,sizeof(lessCount));
        dp[0]=nums[0]=0;
        for(int i=1;i<=n;i++)
            scanf("%d",&nums[i]);
        for(int i=1;i<=n;i++)
        {
            if(nums[i]>nums[i-1])
                lessCount[i] = lessCount[i-1]+1;
            else
                lessCount[i]=0;
            int max=-MAX;
            for(int j=i-1;j>=0;j--)
            {
                if(nums[i]>nums[j])
                {
                    max = max < nums[i]+dp[j] ?  nums[i]+dp[j] :max;
                    j-=lessCount[j];
                }
            }
            dp[i]=max;
        }
        int max=-MAX;
        for(int i=0;i<=n;i++)
                max = max < dp[i] ? dp[i] :max;
        cout<<max<<endl;

    }
    return 0;
} 

 

 

posted @ 2013-04-26 17:45  kbyd  阅读(186)  评论(0编辑  收藏  举报