2018.3.17
// MaxSubsequence2.cpp : 定义控制台应用程序的入口点。 // 分治算法求最大子列和 // 基本思想为二分分治并递归求解左子列最大和、右子列最大和、跨中线子列最大和,比较求出最大和。 //“最大子列和”则被定义为所有连续子列元素的和中最大者。 //例如给定序列{ -2, 11, -4, 13, -5, -2 },其连续子列{ 11, -4, 13 }有最大的和20。 //Now you are supposed to find the largest sum, together with the first and the last numbers of the maximum subsequence. #include "stdafx.h" #include <stdlib.h> #include <stdio.h> #define MAX 100000 int MaxSubseq(int n, int data[]); void Read(int n, int data[]); int Max3(int A, int B, int C); int DivideAndConquer(int data[], int left, int right); int main() { int n; scanf("%d", &n); int data[MAX]; Read(n, data); int result; result = MaxSubseq(n, data); if (result < 0)result = 0; printf("%d", result); return 0; } void Read(int n, int data[]) { int value; for (int i = 0;i < n;i++) { scanf("%d", &value); data[i] = value; } } //求三数最大值 int Max3(int A, int B, int C) { return (A > B ? (A > C ? A : C ): (B > C ? B : C)); } //分治算法求最大子列和,复杂度NlogN int DivideAndConquer(int data[], int left, int right) { //递归终止条件 if (left == right) { if (data[left] > 0)return data[left]; else return 0; } //递归调用 int center = (left + right) / 2; int maxLeftSum = DivideAndConquer(data, left, center);//左子列最大和 int maxRightSum = DivideAndConquer(data, center + 1, right);//右子列最大和,注意从center+1开始 //中线向左扫描 int maxLeftBorderSum = 0, leftBorderSum = 0; for (int i = center;i >= left;i--) { leftBorderSum += data[i]; if (leftBorderSum > maxLeftBorderSum) { maxLeftBorderSum = leftBorderSum; } } //中线向右扫描 int maxRightBorderSum = 0, rightBorderSum = 0; for (int i = center+1;i <=right;i++) { rightBorderSum += data[i]; if (rightBorderSum > maxRightBorderSum) { maxRightBorderSum = rightBorderSum; } } int maxBorderSum = Max3(maxLeftSum, maxRightSum, maxLeftBorderSum+ maxRightBorderSum); //跨边界最大子列和 return maxBorderSum; } int MaxSubseq(int n, int data[]) { return DivideAndConquer(data, 0, n - 1); }