HDU

来源:互联网 发布:用代理不能上公司淘宝 编辑:程序博客网 时间:2024/06/18 14:49

题目:

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

思路:
这题我优化不了,我只能写到三重循环,最后看网上的题解才知道怎么优化。刚开始还爆了空间,心累。
状态 : dp[i][j] i表示前j个数分成i段,第j个数必选。
状态转移: 我最先推出来的是 dp[i][j] = max(dp[i][j-1],dp[i-1][k])+data[j] (i-1<= k <=j-1)
因为j要么和前一项并起来做一段,要么重新开一段。
而且这里可以注意,只有dp[i][j] (j>=i)的时候才有意义,不然根本无法分段,而且dp[i][i] 就是前i项和。
所以可以看出,dp[i][j]的和只与当前的i,和i-1状态下的j值有关,凭这个可以优化空间。
接下来要求i-1状态的max(dp[k]); (i-1<=k<=j-1),是可以在找j这一重循环就能找出来,不用再多写一重。

代码:

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1000005,maxm = 205,inf = 0x3f3f3f3f;int dp[maxn],pre[maxn],data[maxn];int main(){    int m,n;    while(~scanf("%d",&m))    {        scanf("%d",&n);        for(int i = 1; i <= n ; i++) {dp[i] = -inf;pre[i] = 0;scanf("%d",&data[i]);}        dp[0] = 0;pre[0] = 0;        for(int i = 1; i <= m; i++)        {            int Max = -inf;    //Max值就是用来记录(i-1到j-1)的最大值            for(int j = i; j <= n; j++)            {                if(j == i)                    dp[j] = dp[j-1] + data[j];                else                    dp[j] = dp[j-1] > pre[j-1] ? dp[j-1] + data[j] : pre[j-1] + data[j];                pre[j-1] = Max;   //更新pre[j-1],因为下一个循环会用到pre[j],所以不能更新到pre[j]                 if(Max < dp[j]) Max = dp[j];             }        }        int ans = -inf;        for(int i = m; i <= n; i++)    //必须是分m段,所以最后找,而且注意0~m-1是没有意义的。            ans = ans > dp[i] ? ans : dp[i];        printf("%d\n",ans);    }    return 0;}
0 0
原创粉丝点击