题目传送门


为了CSP认证,我又重新拾起了OJ,今天做了一道基础的动态规划题目,其实还是比较简单的


题目描述:

给出一个数列,求出和最大的序列,输出该最大值,以及给序列的起始位置和终止位置


首先写出状态转移方程

dp[i] = max(dp[i-1]+dp[i], dp[i]), i > 0


只要dp[i-1]是大于等于0的,就把他与dp[i]相加,并把值赋给dp[i]

如果dp[i-1]小于0,就抛弃dp[i-1],并更新起点位置为i,注意,本程序中有两个起点,一个begin,一个start,此时只是把begin更新为i,只有当dp[i] > maxSum时,才会把start更新为begin

如果当前dp,也就是dp[i],大于 maxSum,那么就把终止点位置更新为i,并把maxSum重置为dp[i],更新起点


/******************************
HDUOJ 1003 Max Sum
*******************************/

//解题思路,动态规划
//重点是确定状态转移方程 
/*********************************/
//dp[1] = a[1]
//dp[i] = max(dp[i-1]+a[i], a[i])(i >= 2)
/*********************************/
//上面的就是状态转移方程,其实是很简单的
//if dp[i-1]+a[i] > a[i]
//		则可知dp[i-1]>0的 
//此时dp[i-1]对dp[i]是有贡献的
//if dp[i-1]+a[i] < a[i]
//		则可知dp[i-1]<0
//此时dp[i-1]对dp[i]无贡献,舍弃 
#include<stdio.h>
#include<string.h>

#define max(x, y) (x)>(y)?(x):(y);
#define min(x, y) (x)<(y)?(x):(y); 
 
int dp[100010];

int main() {
	int t;
	scanf("%d", &t);
	int kase = 0;
	while(t--) {
		int begin = 1, end = 1, start = 1; 
		memset(dp, 0, sizeof(dp));
		int n;
		scanf("%d", &n);
		for(int i = 1; i <= n; i++)
			scanf("%d", dp + i); 
		int maxSum = dp[1]; 
		for (int i = 2; i <= n; ++i) {
			if(dp[i-1] >= 0)  
				dp[i] = dp[i-1] + dp[i];  
			else  
				begin = i; //临时记录
			if(dp[i] > maxSum) {
				//只有当当前值大于之前的maxSum的时候
				//才会对起始位置和结束位置进行更新
				start = begin;
				end = i;
				maxSum = dp[i];
			}
		}
		if(kase)
			printf("\n");
		kase++;
		printf("Case %d:\n%d %d %d\n", kase, maxSum, start, end);
	}
	return 0;
}