zoukankan      html  css  js  c++  java
  • hdu 1024(dp)

    传送门:Max Sum Plus Plus

    题意:从n个数中选出m段不相交的连续子段,求这个和最大。

    分析:经典dp,dp[i][j][0]表示不取第i个数且前i个数分成j段达到的最优值,dp[i][j][1]表示取了第i个数且前i个数分成j段达到的最优值。

    那么有:

    dp[i][j][0]=max(dp[i-1][j][0],dp[i-1][j][1]).

    dp[i][j][1]=max(dp[i-1][j-1][0]+a[i],max(dp[i-1][j-1][1],dp[i][j][1])+a[i])).

    红色部分略坑,仔细体会一下,因为连续的一段可能拆成多一段刚好符合m段到达最好,不一定得选一段连续的子系列只当成一段最好,可能分成多段更优。

    由于n过大,使用滚动数组优化空间。

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #define N 1000010
    #define inf 0x3f3f3f3f
    using namespace std;
    int dp[2][N][2],a[N];
    int n,m;
    int main()
    {
        while(scanf("%d%d",&m,&n)>0)
        {
            for(int i=1;i<=n;i++)scanf("%d",&a[i]);
            for (int i = 0; i <= m; i++) {
                dp[0][i][0] = dp[1][i][0] = dp[0][i][1] = dp[1][i][1] = -inf;
            }
            dp[0][0][0]=dp[0][0][1]=0;
            for(int i=1,t=1;i<=n;i++,t=!t)
            {
                for(int j=0;j<=i&&j<=m;j++)
                {
                    dp[t][j][0]=max(dp[!t][j][0],dp[!t][j][1]);
                    if(j)dp[t][j][1]=max(dp[!t][j-1][0]+a[i],max(dp[!t][j][1],dp[!t][j-1][1])+a[i]);
                }
            }
            printf("%d
    ",max(dp[n&1][m][0],dp[n&1][m][1]));
        }
    }
    View Code
  • 相关阅读:
    jmeter取样器
    【递归】普通递归关系
    7月,开始奋斗吧!
    BZOJ 1503 郁闷的出纳员
    bzoj 3262: 陌上花开
    BZOJ 2286 消耗战
    莫队
    bzoj1483: [HNOI2009]梦幻布丁
    字符串算法模板
    高级数据结构模板
  • 原文地址:https://www.cnblogs.com/lienus/p/4328764.html
Copyright © 2011-2022 走看看