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

来源:互联网 发布:ubuntu 拨号 编辑:程序博客网 时间:2024/05/16 06:07
题目大意:
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

1061000161001-1600000104-54-344-44-5104-54-344-4456-11-11-161-11-11111-11-11-11-11-1121-11-11-11-11-1171-11-1001-11

ac output

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


0 0
原创粉丝点击