NYOJ 742 —— 最大m段和 【区间DP】

来源:互联网 发布:新手怎样做淘宝客 编辑:程序博客网 时间:2024/06/05 00:18
经典区间DP:最大m段和

“最大连续和问题”是最大m段和问题的一个特例,其实是当m=1的一种特殊情况。

OJ题目:http://acm.nyist.net/JudgeOnline/problem.php?pid=742

  #include <iostream>#include <cstdio>#define INF 0x3f3f3f3fusing namespace std;const int MAXN = 1000000 + 5;typedef long long LL;int a[MAXN];LL dp[MAXN];LL maxn[MAXN];/*    dp[i][j] = max(dp[i][j-1]+a[j], max(dp[i-1][k])+a[j])    (i-1 <= k < j)
  下面的代码进行了两个很重要的优化:1.滚动数组,空间减少一维 2. 通过动态维护上一行中[i-1,j)的最大值,省去k的一重循环
*/int main (){ int T, m, n; scanf("%d", &T); while(T--) { scanf("%d%d", &m, &n); for(int i=1; i<=n; i++) { scanf("%d", &a[i]); } for(int j=0; j<=n; j++) maxn[j] = dp[j] = 0; LL t; for(int i=1; i<=m; i++) { t = -INF; for(int j=0; j<=n; j++) {
          // 把j个数分成比j还多的段,这是不合法的
if(i>j) dp[j] = -INF; else { dp[j] = max(dp[j-1]+a[j], maxn[j-1]+a[j]); // maxn[j-1]已经被使用完毕,所以可以赋值了 maxn[j-1] = t; // t保存第i行、i~j列的最大dp值, // 但是t不能马上赋值给maxn[j],因为下一次循环到j+1时,要用到原来的maxn[j] t = max(t, dp[j]); } } } printf("%lld\n", t); } return 0;}

 

参考:

http://blog.csdn.net/liufeng_king/article/details/8632430

0 0