标签:++ int cin 分治法 end 控制台 out pause return
问题:给出一个长度为n的序列a1,a2,a3....an,求最大连续和,即找到1<=i<=j<=n,是的ai+...+aj最大
1.暴力枚举
int sum = 0;
int max = 0;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
sum = 0;
for (int k = i; k <= j; k++)
sum += a[k];
if (max < sum)
max = sum;
}
}
T(n)=n(n+1)(n+2)/6=O(n3)
2.递推
利用前缀
int s[100];
int max = 0;
s[0] = a[0];
for (int i = 1; i < n; i++)
s[i] = s[i - 1] + a[i];
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int t = i == 0 ? s[j] : s[j] - s[i - 1];
max = Max(max, t);
}
}
T(n)=O(n2)
3.分治法
1)划分:把序列分成元素个数尽量相等的两半;
2) 递归求解:分别求出完全位于左半或者完全位于右半的最佳序列
3)合并:求出起点位于左半,终点位于右半的最大连续和序列,并和子问题的最优解比较
关键在于“合并”步骤,既然起点位于左半,终点位于右半,我们可以认为地把这样的序列分成两部分,
然后独立求解:先寻找最佳起点,然后再寻找最佳终点。
int maxsum3(int a[], int left, int right) { //左闭右开
int i, m, v, L, R, max;
if (right - left == 1) return a[left];
m = left + (right - left) / 2; //第一步,划分成[left,m),[m,right)
max = Max(maxsum3(a, left, m), maxsum3(a, m, right));
//第二步,递归求解
//第三步,合并
v = 0; L = a[m - 1];
for (i = m - 1; i >= left; i--)
L = Max(L, v += a[i]);
v = 0; R = a[m];
for (i = m; i < right; i++)
R = Max(R, v += a[i]);
return Max(max, L + R);
}
// 练习.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
using namespace std;
int Max(int a, int b) {
return a > b ? a : b;
}
//暴力枚举
int maxsum1(int a[], int n) {
int sum = 0;
int max = 0;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
sum = 0;
for (int k = i; k <= j; k++)
sum += a[k];
if (max < sum)
max = sum;
}
}
return max;
}
//递推前缀
int maxsum2(int a[], int n)
{
int s[100];
int max = 0;
s[0] = a[0];
for (int i = 1; i < n; i++)
s[i] = s[i - 1] + a[i];
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int t = i == 0 ? s[j] : s[j] - s[i - 1];
max = Max(max, t);
}
}
return max;
}
//分治法
int maxsum3(int a[], int left, int right) { //左闭右开
int i, m, v, L, R, max;
if (right - left == 1) return a[left];
m = left + (right - left) / 2; //第一步,划分成[left,m),[m,right)
max = Max(maxsum3(a, left, m), maxsum3(a, m, right));
//第二步,递归求解
v = 0; L = a[m - 1]; //第三步,合并
for (i = m - 1; i >= left; i--)
L = Max(L, v += a[i]);
v = 0; R = a[m];
for (i = m; i < right; i++)
R = Max(R, v += a[i]);
return Max(max, L + R);
}
int main()
{
int n;
int a[100];
cin >> n;
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int s1 = maxsum1(a, n);
int s2 = maxsum2(a, n);
int s3 = maxsum3(a, 0, n);
cout << s1 << endl;
cout << s2 << endl;
cout << s3 << endl;
system("pause");
return 0;
}
标签:++ int cin 分治法 end 控制台 out pause return
原文地址:https://www.cnblogs.com/zuoyou151/p/8998928.html