标签:cst bsp alt es2017 blank set lan font int
题意:给定序列,求找出m个子序列的和使它们最大,子序列无交叉。
题解:又是最大子序列和增强版。但是这回让找m个,我还是没有思路。网上看到的思路无一例外都是:
dp[i][j]表示前j个数分成i个子序列能获得的最大值。它有两大部分转移过来,一个是j是第i个序列的首元素,则dp[i][j]由dp[i-1][t]转移过来,即前t个数分成i-1个子序列;另一种自然就是第j个数不是第i个子序列的首元素,所以由前j-1个数分成i个子序列的状态dp[i][j-1]转移过来。但是数据很大,二维数组开不下,而且m还未知,所以想优化到一维,dp[j]。用pre[j-1]记录前一个状态,因为当前层状态只由前面一层推过来。不细说了,这里详细解释网上博客一大堆。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 const int MAXN = 1000000; 8 const ll INF = 1e12; 9 int dp[MAXN], pre[MAXN], a[MAXN]; 10 11 int main() 12 { 13 int n, m, i, j; 14 while (scanf("%d%d",&m,&n)==2) 15 { 16 memset(dp, 0, sizeof(dp)); 17 memset(pre, 0, sizeof(pre)); 18 for (i = 1; i <= n; i++) 19 scanf("%lld", &a[i]); 20 ll MAX; 21 for (i = 1; i <= m; i++) 22 { 23 MAX = -INF; 24 for (j = i; j <= n; j++) { 25 dp[j] = max(dp[j - 1], pre[j - 1]) + a[j]; 26 pre[j - 1] = MAX; 27 if (MAX < dp[j]) 28 MAX = dp[j]; 29 } 30 } 31 printf("%lld\n", MAX); 32 } 33 return 0; 34 }
我看见网上还有人说用滚动数组,一看就是上面的做法,可是我理解的滚动数组是只用一个数组每次求解的时候覆盖和使用上一次的结果。。。。我把dp[]数组改成了二维,第一维大小为2,每次来回换一下就好了。但不知道为啥效率比上面的低好多,不是一样的嘛?再交一回。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 const int MAXN = 1000000; 8 const ll INF = 1e12; 9 int dp[2][MAXN], pre[MAXN], a[MAXN]; 10 11 int main() 12 { 13 int n, m, i, j; 14 while (scanf("%d%d",&m,&n)==2) 15 { 16 memset(dp, 0, sizeof(dp)); 17 memset(pre, 0, sizeof(pre)); 18 for (i = 1; i <= n; i++) 19 scanf("%lld", &a[i]); 20 ll MAX; 21 int c=0; 22 for (i = 1; i <= m; i++) 23 { 24 MAX = -INF; 25 for (j = i; j <= n; j++) { 26 dp[c][j] = max(dp[c][j - 1],dp[c^1][j - 1]) + a[j]; 27 dp[c ^ 1][j - 1] = MAX; 28 if (MAX < dp[c][j]) 29 MAX = dp[c][j]; 30 } 31 } 32 printf("%lld\n", MAX); 33 } 34 return 0; 35 }
hdu 1024 MAX Sum Plus Plus【dp】
标签:cst bsp alt es2017 blank set lan font int
原文地址:http://www.cnblogs.com/zxhyxiao/p/7410784.html