zoukankan      html  css  js  c++  java
  • hdu 1024(最大和连续子序列增强版)

    题意:最大和连续子序列的增强版,要求从一序列中取出若干段,这些段之间不能交叉,使得和最大并输出。

    分析:用dp[i][j]表示前j个数取出i段得到的最大值,那么状态转移方程为dp[i][j]=max(dp[i][j-1]+a[j],dp[i-1][k]+a[j])  i-1<=k<=j-1

    这个状态转移方程表达了两种不同的选择:第一个就是第j个连在第j-1个所在的段的后面,第二个就是第j个为新的一段的第一个数字。

    由于数字的个数比较大,而题目中给定的m未知,怕超内存,所以要想办法开设一维数组来代替,后来发现可以用dp[j]表示表示到第j个的时候

    最大和。解决了空间的问题了,现在就是时间的问题了,dp[i-1][k]  i-1<=k<=j-1,如果这里用for循环去写的话,由于题目中给定的数字个数

    太大,那肯定会超时的!所以我们可以开设一个数组来记录上一状态的j-1个前的最大值,具体看代码实现吧!!

    代码实现:

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    using namespace std;
    int a[1000001],dp[1000001],max1[1000001];
    int max(int x,int y)
    {
        return x>y?x:y;
    }
    int main()
    {
        int i,j,n,m,temp;
        while(scanf("%d%d",&m,&n)!=EOF)
        {
            for(i=1;i<=n;i++)
            {
                scanf("%d",&a[i]);
                dp[i]=0;
                max1[i]=0;
            }
            dp[0]=0;
            max1[0]=0;
            for(i=1;i<=m;i++)//这里可以省空间
            {
                temp=-100000000;
                for(j=i;j<=n;j++)
                {
                    dp[j]=max(dp[j-1]+a[j],max1[j-1]+a[j]);
                    max1[j-1]=temp;//为i+1的时候做准备
                    temp=max(temp,dp[j]);//保存前j个段数为i时的最大值
                }
            }
            printf("%d
    ",temp);
        }
        return 0;
    }
  • 相关阅读:
    STL中set求交集、并集、差集的方法
    Vijos 1308 埃及分数(迭代加深搜索)
    POJ 1161 Walls(Floyd , 建图)
    UVa 1601 万圣节后的早晨
    dp之完全背包
    dp之取数字问题
    dp之最长公共子序列
    枚举排列
    poj 3187 暴力枚举
    poj 2431 优先队列,贪心
  • 原文地址:https://www.cnblogs.com/jiangjing/p/3214729.html
Copyright © 2011-2022 走看看