hdu1024(m段子段和最大)

链接:点击打开链接

题意:n个数分成m段不相交子段和最大

代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f3f;
int a[1000005],sum[1000005];
int dp[2][1000005][2];
int main(){                                     //因为是分成m段,因此和容易想到
    int n,m,i,j,tmp;                            //dp[i][j]为前i个数分成j段的最大和
    while(scanf("%d%d",&m,&n)!=EOF){            //但是再每次合并时,需要判断当前数是否选
        memset(dp,-INF,sizeof(dp));             //因此需要再加一维记录前一个数的状态
        for(i=1;i<=n;i++){
            scanf("%d",&a[i]);
            sum[i]=sum[i-1]+a[i];
        }
        tmp=-INF;
        dp[0][0][0]=0;
        for(i=1;i<=n;i++){
            if(sum[i-1]+a[i]>a[i]){
                dp[i%2][1][1]=sum[i-1]+a[i];
                sum[i]=sum[i-1]+a[i];
            }
            else{
                sum[i]=a[i];
                dp[i%2][1][1]=a[i];
            }
            dp[i%2][1][0]=tmp;                  //长度是1时就是最大子段和
            tmp=max(tmp,sum[i]);
            for(j=2;j<=m;j++){
                if(i<j)
                break;
                if(i-1>=j){                     //考虑i-1个数能不能分成j份
                    dp[i%2][j][1]=max(max(dp[(i-1)%2][j-1][0],dp[(i-1)%2][j-1][1]),dp[(i-1)%2][j][1])+a[i];
                    dp[i%2][j][0]=max(dp[(i-1)%2][j][0],dp[(i-1)%2][j][1]);
                }
                else{
                    dp[i%2][j][0]=-INF;
                    dp[i%2][j][1]=max(dp[(i-1)%2][j-1][0],dp[(i-1)%2][j-1][1])+a[i];
                }
            }
        }
        printf("%d\n",max(dp[n%2][m][1],dp[n%2][m][0]));
    }
    return 0;
}
时间: 2024-08-09 10:43:41

hdu1024(m段子段和最大)的相关文章

P1121 环状最大两段子段和

P1121 环状最大两段子段和 题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的第一行是一个正整数N(N\le 2\times 10^{5})(N≤2×10?5??),表示了序列的长度. 第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列,第一个数和第N个数是相邻的. 输出格式: 输入文件maxsum2.out仅包括1个整数,为最大的两段子段和是多少. 输入输出

环状最大两段子段和

题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的第一行是一个正整数N,表示了序列的长度. 第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列,第一个数和第N个数是相邻的. 输出格式: 输入文件maxsum2.out仅包括1个整数,为最大的两段子段和是多少. 输入输出样例 输入样例#1: 7 2 -4 3 -1 2 -4 3 输出样例#1: 9题解:动态规划最大两

洛谷P1121 环状最大两段子段和

题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的第一行是一个正整数N,表示了序列的长度. 第2行包含N个绝对值不大于10000的整数A[i],描述了这段序列,第一个数和第N个数是相邻的. 输出格式: 输入文件maxsum2.out仅包括1个整数,为最大的两段子段和是多少. 输入输出样例 输入样例#1: 7 2 -4 3 -1 2 -4 3 输出样例#1: 9 说明 [样例说明]

[ACM] POJ 2479 Maximum sum (动态规划求不相交的两段子段和的最大值)

Maximum sum Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 33363   Accepted: 10330 Description Given a set of n integers: A={a1, a2,..., an}, we define a function d(A) as below: Your task is to calculate d(A). Input The input consists o

洛咕P1121环状最大两段子段和

序列dp 题目传送门 我们先不考虑环状,只考虑如何求出最大两段子段和 最大子段和转移方程: f[i]表示以i为结尾的最大子段和    f[i]=max(f[i-1],0)+a[i] ans[i]表示在前i项中的最大子段和    ans[i]=max(f[i],ans[i-1]); 最小子段和同理 想法1:暴力dfs,时间复杂度O(2^n),不T才怪 期望得分:0 想法2:斩环,先求一次最大子段和,将整个子段都置为-inf,再求一遍 hack数据: 6 -3 5 2 1 8 -9 正确:15 错误

【题解】环状最大两段子段和

哈哈哈哈就在快要放弃的时候盯着眼前画的图片突然之间柳暗花明( ? ?ω?? )? 首先,最大子段和想必大家都会做:对于每一个节点而言,只有选与不选两种可能的情况,枚举即可,贪心的省去一定不优的情况.然后再来考虑:如果没有环的话我们可以怎么做?没有环的情况下,我们所要做的就是找出不交叉的两个最大子段和,自然地联想到用一个分界线来分割这两个子段.g[i]代表1~i中的最大子段和,f[i]表示i~n中的最大子段和.此时的答案则是max(f[i] + g[i-1]).这几个操作的复杂度都是O(n)的.

HDU1024 最大m子段和

Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 27582    Accepted Submission(s): 9617 Problem Description Now I think you have got an AC in Ignatius.L's "Max Sum" problem.

HDU1024 多段最大和 DP

题目大意: 在n个数,求不重复的m段中的数据总和的最大值 令dp[i][j]表示将前j个数分成 i 段时得到的最大值(必取到第 j 个数) 状态转移可列为 dp[i][j]=Max(dp[i][j-1]+a[j] , Max( dp[i-1][k] ) + a[j] ) 0<k<j 1 #include <cstdio> 2 #include <cstring> 3 #include <string> 4 #include <iostream>

LuoGuP1121:环状最大两段子段和

Pre 专业挖坑,这个坑是去年挖的,现在已经发霉了. Solution 先做一次最大子段,再做一次全部取负的最大子段,就可以了. 注意特判如果不成立的情况,也就是取负之后可能选的只剩下一个,这时是只有一个正数的情况. 或许还有全部负数的情况,题解没说要特判,我还是一起判了. Code #include <cstdio> #include <cstring> #include <limits.h> using namespace std; inline int max (