为了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;
}