个人原创,转载请注明出处,谢谢!
一、 目的
input: n个元素的数组;
output: 在数组中查找相邻数的最大和;
constrain: 如最大和为负数,则最大和为0,即一个也不选。
二、算法原理
要解决x[n]的最大和问题,可递归解决两个规模近似为n/2的子问题,然后将他们的答案进行合并以得到整个问题的答案。即如下图将x[n]转化为两个子数组x[a]和x[b]:
考虑到a和b的并集也可能产生最大和,所以最大和只能在a,b或a与b中的并集产生,如下图:
即在子数组x[a],x[m]和x[b]中产生。
三、 代码
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXN 10000000
int n;
float x[MAXN];
void sprinkle()
{
int i;
for (i = 0; i < n; i++) {
x[i] = 1 - 2*( (float) rand()/RAND_MAX);
}
}
float maxfun(float a, float b)
{
return a > b ? a : b;
}
#define max(a, b) maxfun(a, b)
float get_max_sum (int l, int u)
{
int i, m;
float lmax, rmax, sum;
if (l > u) {
return 0;
}
if (l == u) {
return max(0, x[l]);
}
m = (l + u) / 2;
lmax = sum = 0;
for (i = m; i >= l; i--) {
sum += x[i];
if (sum > lmax)
lmax = sum;
}
rmax = sum = 0;
for (i = m + 1; i <= u; i++) {
sum += x[i];
if (sum > rmax) {
rmax = sum;
}
}
return max(lmax + rmax,
max(recmax(l, m), recmax(m+1, u)));
}
int main()
{
float max_sum;
while (scanf("%d", &n) != EOF) {
sprinkle();
start = clock();
max_sum = -1.0;
max_sum = get_max_sum();
printf(“max sum = %f/n”, max_sum);
}
return 0;
}
四、代码注解
/*使用随机数[-1,1]填充数组,使得数组内元素有正有负,且随机排布*/
void sprinkle()
{
int i;
for (i = 0; i < n; i++) {
x[i] = 1 - 2*( (float) rand()/RAND_MAX);
}
}
float maxfun(float a, float b)
{ return a > b ? a : b;
}
#define max(a, b) maxfun(a, b)
/*求数组x[l,u]内(递归时为子数组)相邻元素的最大和*/
float get_max_sum (int l, int u)
{
int i, m;
float lmax, rmax, sum;
/* 子数组内没有任何元素 */
if (l > u) {
return 0;
}
/*子数组内仅有一个元素*/
if (l == u) {
return max(0, x[l]); /*此时只需返回0和x[l]中大的一个即可*/
}
m = (l + u) / 2; /*求中间值,为折半求和准备*/
/*开始折半求和*/
/* 先求m左侧子数组x[l, m]中(含m)的最大和*/
lmax = sum = 0;
for (i = m; i >= l; i--) {
sum += x[i];
if (sum > lmax) {
lmax = sum; /*通过不断的比较以获取左侧的最大和*/
}
}
/* 再求右侧子数组x(m, u]中的(不含m)最大和*/
rmax = sum = 0;
for (i = m + 1; i <= u; i++) {
sum += x[i];
if (sum > rmax) {
rmax = sum; /*通过不断的比较以获取右侧的最大和*/
}
}
return max(lmax + rmax,
max(recmax(l, m), recmax(m+1, u)));
/*实际就是求各个子数组的最大和:
左右的并集,m的左侧和m的右侧三个最大和,
注意求左右侧最大和时又进一步进行递归求和。
*/
}
int main()
{
float max_sum;
while (scanf("%d", &n) != EOF) {
/*初始化数组*/
sprinkle();
max_sum = get_max_sum();
printf (“max sum = %f/n”, max_sum);
}
return 0;
}