hdu 1024 Max Sum Plus Plus

https://vjudge.net/problem/HDU-1024

题意:

给出一个数m和n,再给出n个数,要求选出m个不相交区间,之后找出这个m个不相交区间中的区间之和最大值。

思路:

动态规划,dp[i][j]表示前j个数选了i个区间的最大值,那么dp[i][j]的最大值要么是把当前的a[j]加到第i个区间中,要么是选前i - 1个区间中的最大值,把当前的a[j]作为第i个区间的第一个元素。

于是这样的转移方程就为dp[i][j] = max(dp[i][j-1] + a[j],dp[i-1][k] + a[j]) (i - 1 <= k <= j - 1)。

首先,dp[i][j]如果用二维数组的话,i和j的最大值都是1e6,那么肯定空间会爆,所以必须降维优化,我们观察到实际上如果用dp[j]表示取到第j个数的时候的最大,也是可行的。然后时间复杂度的优化,我们可以用一个数组来保存取到第i个区间时取到前 j - 1个数的最大值。

这样转移方程就变成了dp[j] = max(dp[j-1] + a[j],maxn[j-1] + a[j]),maxn[j - 1] 就是在第i个区间时,取i - 1 到 j - 1个数之中的最大值。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 using namespace std;
 5 int a[1000005],dp[1000005],maxn[1000005];
 6 
 7 int main()
 8 {
 9     int n,m;
10     
11     while (scanf("%d%d",&m,&n) != EOF)
12     {
13         for (int i = 1;i <= n;i++)
14             scanf("%d",&a[i]);
15         
16         memset(dp,0,sizeof(dp));
17         
18         memset(maxn,0,sizeof(maxn));
19         
20         int tmp;
21         
22         for (int i = 1;i <= m;i++)
23         {
24              tmp = -1e8;
25             
26             for (int j = i;j <= n;j++)
27             {
28                 dp[j] = max(dp[j-1] + a[j],maxn[j-1] + a[j]);
29                 
30                 maxn[j-1] = tmp;//这里保存的是上一个
31                 
32                 tmp = max(tmp,dp[j]);
33             }
34         }
35         
36         printf("%d\n",tmp);
37     }
38     return 0;
39 }

 

posted @ 2017-09-12 20:36  qrfkickit  阅读(128)  评论(0编辑  收藏  举报