UVA - 507 - Jill Rides Again (dp最大子段和)

题目大意:
Jill喜欢骑自行车,但是自从他的城市有了公交系统后,他就比较少骑车了,于是他买了一个折叠自行车,这样他就可以把自行车带到公交车上,当他下车后,他就可以继续骑车。
现在b条道路,每条道路有n个公交站点,两个站点间都有一个喜欢值,现在问你能否求出,哪两个站点间的喜欢值最大,如果有多个最大值,输出其中距离最远的站点。


解析:
题如果用普通枚举起点和终点的O(n^3)肯定超时,所以要用dp来做。

最大字段和dp公式的推导:

若记dp[j] = max(a[i]+a[i+1]+..+a[j]),
其中1 <= i <= j,并且1<=j<=n
则所求的最大子段和为max(dp[j]),1 <= j <= n。
由dp[j]的定义可易知,
当dp[j-1]>0时
dp[j] = dp[j-1]+a[j],
否则
dp[j] = a[j]
故dp[j]的动态规划递归式为:

dp[j] = max(dp[j-1]+a[j],a[j]),1<=j<=n。

#include <stdio.h>
#include <string.h>
const int INF = 0x3f3f3f;
const int N = 20010;
int arr[N],dp[N];
int main() {
	int t,n,cas = 1;
	scanf("%d",&t);
	while(t--) {
		memset(dp,0,sizeof(dp));
		scanf("%d",&n);
		arr[0] = 0;
		for(int i = 1; i < n; i++) {
			scanf("%d",&arr[i]);
		}
		int max;
		int left,right,start;
		left = right = start = 1;
		dp[1] = max = arr[1];
		for(int i = 2; i < n; i++) {
			if(dp[i-1] >= 0) {
				dp[i] = dp[i-1] + arr[i];
			}else {
				dp[i] = arr[i];
				start = i;
			}
			if(max < dp[i] || max == dp[i] && i - start > right - left) {
				left = start;
				right = i;
				max = dp[i];
			}
		}
		if(max >= 0) {
			printf("The nicest part of route %d is between stops %d and %d\n",cas++,left,right+1);
		}else {
			printf("Route %d has no nice parts\n",cas++);
		}
	}
	return 0;
}

附上一组样例:

input

10

6
1
0
0
0
1


6
1
0
0
1
-1

6
0
0
0
0
0

10
4
-5
4
-3
4
4
-4
4
-5

10
4
-5
4
-3
4
4
-4
4
5

6
-1
1
-1
1
-1

6
1
-1
1
-1
1

11
1
-1
1
-1
1
-1
1
-1
1
-1

12
1
-1
1
-1
1
-1
1
-1
1
-1
1

7
1
-1
1
-100
1
-1
1

ac output

The nicest part of route 1 is between stops 1 and 6
The nicest part of route 2 is between stops 1 and 5
The nicest part of route 3 is between stops 1 and 6
The nicest part of route 4 is between stops 3 and 9
The nicest part of route 5 is between stops 3 and 10
The nicest part of route 6 is between stops 2 and 5
The nicest part of route 7 is between stops 1 and 6
The nicest part of route 8 is between stops 1 and 10
The nicest part of route 9 is between stops 1 and 12
The nicest part of route 10 is between stops 1 and 4


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值