您的位置:首页 > 其它

HDU 1024 Max Sum Plus Plus

2013-01-05 10:24 302 查看
DP问题

解题步骤已经在代码中解释的很清楚了

DP题的代码个人认为是挺难理解的,但是,如果理解了就会觉得很简单

需要注意一下的是,题目让分两段,必须就得分两段,即使分成两段之后的总和反而更小

比如代码注释中我举得例子

package 动态规划;

import java.util.Scanner;

public class _1024_选择多次最长子序列 {

/**
* m=3,n=6      | -1 | 4 | -2 | 3 | -2 |  3  |
*
* now:	   | 0  | -1 | 4 | 2  | 5 | 3  |  6  |
*
* pre:    |-99 | -1 | 4 | 4  | 5 | 5  |  0  |
*
* now:    | 0  | -1 | 3 | 2  | 7 | 5  |  8  |
*
* pre:	   |-99 |-99 | 3 | 3  | 7 | 7  |  0  |
*
* now:    | 0  | -1 | 3 | 1  | 6 | 5  |  10 |
*
* pre:    |-99 |-99 |-99| 1  | 6 | 6  |  0  |
*
* @param args
*/

// http://acm.hdu.edu.cn/showproblem.php?pid=1024 // 状态: dp[i][j] --- 表示前j个数中的最大i段子段和,并且a[j]包涵于最后一个子段
// 状态转移方程: dp[i][j]=max{dp[i][j-1]+A[j],dp[i-1][t]+a[j] (i-1<=t<n-m+i) }
// 关于状态转移方程的解释:
// dp[i][j]由两种情况得到,
// 一、a[j]包涵于最后一个子段,这种情况的最大值就是EDP[i][j-1]+a[j];
// 二、a[j]就是最后一个子段,这种情况的最大值是 dp[i-1][t]+a[j] (i-1<=t<=n-m+i) 中
// 的最大值.
// 以下用滚动数组进行DP
// 在求 dp[i][j]时也顺便把 max{dp[i - 1][t]} ( i - 1 <= t < j) 求出来,这样的话
// 时间复杂度仅为 O(N*(N - M + 1)) , 空间为 O( N )

public static void main(String[] args) {

Scanner sc = new Scanner(System.in);

while (sc.hasNext()) {

int m = sc.nextInt();
int n = sc.nextInt();

// 输入
int[] num = new int[n + 1];

// 滚动数组
// now[j]代表在加上num[j]这个数之后最大可能的值,可能会更小
int[] now = new int[n + 1];
// pre[j]代表在num[j+1]这个数之前的最优值
int[] pre = new int[n + 1];

// 输入
for (int i = 1; i <= n; i++) {

num[i] = sc.nextInt();

}

// 初始化max_pre
int max_pre = 0;

// 遍历m次
for (int i = 1; i <= m; i++) {

// 刚开始max_pre值为整数型最小值
max_pre = -Integer.MAX_VALUE;

// 遍历i→n
//这里j=i的意思是,前边i个数已经没得选了,因为必定得分段,即必须得选上
//注意,now[j],j=i时,这个数也是不得不选的

//从j开始,也是为了让pre[j-1]是负最大值,j=i+1时用得着
//表示下一个i,第i+1个数之前没得选择,它前边只能是i个值相加
//之后就有一定的选择性了

//比如,运行程序,测试一下:
//				1 2 -1 4
//				4
//				2 2 -1 4
//				3
//可见,第二次 两个都选上了,虽然结果还不如选一段
for (int j = i; j <= n; j++) {

//now不一定是最优的,now是在不断的尝试now或是max_pre加新的值
now[j] = max(now[j - 1] + num[j], pre[j - 1] + num[j]);
//每一个pre[j-1]都是对于第i次,第j个数之前最优的
pre[j - 1] = max_pre;

//每行的最后一个数不一定是最大的,max_pre才是
if (now[j] > max_pre) {

//max_pre取当前最大值
max_pre = now[j];

}
}
}

System.out.println(max_pre);

}
}

public static int max(int a, int b) {
if (a > b)
return a;
return b;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: