您的位置:首页 > 其它

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

2016-05-18 21:37 330 查看
经典区间DP:最大m段和
“最大连续和问题”是最大m段和问题的一个特例,其实是当m=1的一种特殊情况。

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

#include <iostream>
#include <cstdio>
#define INF 0x3f3f3f3f
using 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: