Max Sum Plus Plus HDU - 1024(动态规划求最大M子段和)

题意:

----最大M子段和问题
给定由 n个整数(可能为负整数)组成的序列以及一个正整数 m,要求确定序列的 m个不相交子段,使这m个子段的总和达到最大,求出最大和。

题目:

Now I think you have got an AC in Ignatius.L’s “Max Sum” problem. To be a brave ACMer, we always challenge ourselves to more difficult problems. Now you are faced with a more difficult problem.

Given a consecutive number sequence S 1, S 2, S 3, S 4 … S x, … S n (1 ≤ x ≤ n ≤ 1,000,000, -32768 ≤ S x ≤ 32767). We define a function sum(i, j) = S i + … + S j (1 ≤ i ≤ j ≤ n).

Now given an integer m (m > 0), your task is to find m pairs of i and j which make sum(i 1, j 1) + sum(i 2, j 2) + sum(i 3, j 3) + … + sum(i m, j m) maximal (i x ≤ i y ≤ j x or i x ≤ j y ≤ j x is not allowed).

But I`m lazy, I don’t want to write a special-judge module, so you don’t have to output m pairs of i and j, just output the maximal summation of sum(i x, j x)(1 ≤ x ≤ m) instead. _

Input

Each test case will begin with two integers m and n, followed by n integers S 1, S 2, S 3 … S n.
Process to the end of file.

Output

Output the maximal summation described above in one line.

Sample Input

1 3 1 2 3
2 6 -1 4 -2 3 -2 3

Sample Output

6
8

思路:

很明显,我们不能知道某一点是否该加入段中,加入到那一段中,不能用贪心写,那么只能用动态规划,看某点j是否需要加入i段中,或是新开一段作为新段的开头。

AC代码

#include
#include
#include
using namespace std;
typedef long long ll;
const int  M=1e6+10;
const int inf=0x3f3f3f3f;
int n,m,dp[M],f[M],s[M],ans;
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1; i<=m; i++)
            scanf("%d",&f[i]);
        memset(dp,0,sizeof(dp));
        memset(s,0,sizeof(s));
        for(int i=1; i<=n; i++)
        {
            ans=-inf;
            for(int j=i; j<=m; j++)
            {
                dp[j]=max(dp[j-1]+f[j]/*f[j]属于第i段*/,s[j-1]+f[j]/*f[j]不属于第i段为新的段加上前i-1段,看是否较大*/);/*看该点是否为新段的开始*/
                s[j-1]=ans;/*上一段(i-1)到j-1点的最大值*/
                ans=max(dp[j],ans);/*在第i段第j点的最大值,为当前最大值*/
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(dp)