动态规划 求部分和

来源:互联网 发布:nginx web服务器配置 编辑:程序博客网 时间:2024/06/11 01:02

子串和

时间限制:5000 ms  |  内存限制:65535 KB
难度:3
描述
给定一整型数列{a1,a2...,an},找出连续非空子串{ax,ax+1,...,ay},使得该子序列的和最大,其中,1<=x<=y<=n。
输入
第一行是一个整数N(N<=10)表示测试数据的组数)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的一行里有n个整数I(-100=<I<=100),表示数列中的所有元素。(0<n<=1000000)
输出
对于每组测试数据输出和最大的连续子串的和。
样例输入
151 2 -1 3 -2
样例输出
5 

用数组A[N]记录所要求的数组,用数组B[N]来记录连续子段和的状态

通过分析,可以知道:

当B[K]>0时,无论B[K]为何值,B[K]=B[K-1]+A[K]

当B[K]<0时,也就是B[K]记录到一个A[J]是负的,可以把B[K]变成负的,那么B[J]记录的这一段应该截掉,应为无论后面的A[K]多大,加上个负数总不可能是最大的子段和,因此将B[K]=A[K],重新开始记录。

 

故动态转移方程便可得出

B[K] = MAX(B[K-1]+A[K] , A[K])

(转)
#include<stdio.h>int *p;int max_dp(int n,int *p){int i;int minsMark = 0; //记录是否全为负数for(i = 0 ; i < n ;i++){if(p[i] < 0)minsMark++;}if(minsMark == n)  //如果全是负数,输出第一个值printf("%d",p[0]);else{int sum = 0, b;for(int i = 0; i < n ;i++){if(b > 0){b+=p[i];}else{b = p[i];}if(b > sum){sum = b;}}return sum;}}int main(){int rank;scanf("%d",&rank);int i;for(i = 0 ; i < rank ; i++) {int n;scanf("%d",&n);p = new int[n];int j;for(j = 0 ;j < n ;j++){scanf("%d",&p[j]);}printf("%d",max_dp(n,p));}}
0 0
原创粉丝点击