zoukankan      html  css  js  c++  java
  • 最大连续和

    问题:给出一个长度为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;
    }
    
  • 相关阅读:
    Tensorflow揭秘
    今日Q群:QQ群众群友反馈问题的归纳总结
    新闻:小娜来了 微软语音助手正式入华
    原创:如何统计并过滤行中单元格有颜色的值
    转载:案例用Excel对会员客户交易数据进行RFM分析
    转载:推荐给每个“数据分析师”看的PPT——关于开会的那点事
    原创:XXX公司-基于SAP的库存管理系统解决方案
    原创:如何实现在Excel通过循环语句设置指定行的格式
    原创:用VBA实现将鼠标选择的单元格按照指定格式合并并复制到剪切板
    原创:《Excel在零售及电商行业数据化管理中的应用》之“什么是数据化管理?
  • 原文地址:https://www.cnblogs.com/zuoyou151/p/8998928.html
Copyright © 2011-2022 走看看