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 }
康复训练中~欢迎交流!