1. 程式人生 > >計算最大子段(分治法)

計算最大子段(分治法)

這個程式使用分治法計算最大子段,結果為最大子段之和,用遞迴程式實現。

原始資料使用隨機函式生成。

採用結構化程式設計,可以很容易改為從標準輸入或檔案讀入資料,只需要修改函式getData即可。

資料個數由巨集定義給出,也可以輕鬆地改為輸入
/*
 * 最大子段演算法程式
 */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 13

void getData(int [], int);

int maxsumfun(int a[], int left, int right);

int main(void)
{
    int a[N], i;

    getData(a, N); /* 獲得資料放入陣列a中 */

    printf("datas: ");
    for (i = 0; i < N; i++)
        printf("%d ", a[i]);
    printf("\n");

    int ms;
    ms = maxsumfun(a, 0, N - 1);

    printf("maxsum=%d\n", ms);

    return 0;
}

int maxsumfun(int a[], int left, int right)
{
    int maxsum = 0;

    if(left == right)
    {
        if(a[left] > 0)
            maxsum = a[left];
        else
            maxsum = 0;
    }
    else
    {
        int mid, leftsum, rightsum, midsum;

        mid = (left + right) / 2;
        leftsum = maxsumfun(a, left, mid);
        rightsum = maxsumfun(a, mid+1, right);

        int leftsum1 = 0;
        int lefts = 0;
        int i;
        for(i=mid; i>=left; i--)
        {
            lefts += a[i];
            if(lefts > leftsum1)
                leftsum1 = lefts;
        }

        int rightsum1 = 0;
        int rights = 0;
        for(i=mid+1; i<=right; i++)
        {
            rights += a[i];
            if(rights > rightsum1)
                rightsum1 = rights;
        }

        midsum = leftsum1 + rightsum1;
        if(midsum < leftsum)
            maxsum = leftsum;
        else
            maxsum = midsum;
        if(maxsum < rightsum)
            maxsum = rightsum;
    }
    return maxsum;
}

void getData(int d[], int n)
{
    time_t t;
    srand((unsigned) time(&t));  /* 設定隨機數起始值 */

    int i;
    for(i=0; i < n; i++)
        d[i] = rand() % 30 - 10; /* 獲得-10--20之間的整數值 */
}

關鍵程式碼:
// 遞迴計算最大子段
int maxsumfun(int a[], int left, int right)
{
    int maxsum = 0;

    if(left == right)
    {
        if(a[left] > 0)
            maxsum = a[left];
        else
            maxsum = 0;
    }
    else
    {
        int mid, leftsum, rightsum, midsum;

        mid = (left + right) / 2;
        leftsum = maxsumfun(a, left, mid);
        rightsum = maxsumfun(a, mid+1, right);

        int leftsum1 = 0;
        int lefts = 0;
        int i;
        for(i=mid; i>=left; i--)
        {
            lefts += a[i];
            if(lefts > leftsum1)
                leftsum1 = lefts;
        }

        int rightsum1 = 0;
        int rights = 0;
        for(i=mid+1; i<=right; i++)
        {
            rights += a[i];
            if(rights > rightsum1)
                rightsum1 = rights;
        }

        midsum = leftsum1 + rightsum1;
        if(midsum < leftsum)
            maxsum = leftsum;
        else
            maxsum = midsum;
        if(maxsum < rightsum)
            maxsum = rightsum;
    }
    return maxsum;
}


相關推薦

計算大子治法

這個程式使用分治法計算最大子段,結果為最大子段之和,用遞迴程式實現。 原始資料使用隨機函式生成。 採用結構化程式設計,可以很容易改為從標準輸入或檔案讀入資料,只需要修改函式getData即可。 資料個數由巨集定義給出,也可以輕鬆地改為輸入。 /* * 最大子段演算法程

平面接近點對問題治法

技術 src void emp image mage tar 分治 pac 問題描述參見:https://www.cnblogs.com/zyxStar/p/4591897.html 代碼參考:http://blog.csdn.net/qq_28666193/articl

大連續和治法O(nlogn)

分解:將序列分解成元素個數儘量相等的子序列,求出每個子序列的最大連續和 合併:合併子問題得到原問題的解,由於最大連續和的子序列要麼完全在中點左邊,要麼完全在中點右邊,要麼就是橫跨左右兩邊,所以比較這幾

C語言實現快速排序法治法

下一個 enter hang partition 等於 就是 tor log markdown title: 快速排序法(quick sort) tags: 分治法(divide and conquer method) grammar_cjkRuby: true ---

合並排序治法

for 數組 數組a 想要 -s fin size 外部 ... 使用分治法進行合並排序,問題描述參見:https://www.cnblogs.com/jingmoxukong/p/4308823.html 算法核心: //merge_sort.h #ifndef

快速排序治法

ios type font nbsp def 註意 class 裏的 span 問題描述參考:http://blog.csdn.net/code_ac/article/details/74158681 算法實現部分: //random_quick_sort.cpp

hdu-1231 連續大子序列動態規劃

得到 繼續 用例 using 規劃 mem 空格 編寫 序號 Time limit1000 ms Memory limit32768 kB 給定K個整數的序列{ N1, N2, ..., NK },其任意連續子序列可表示為{ Ni, Ni+1, ..., Nj },其中

Codeforces 448C Painting Fence治法

劃分 .com 規劃 == sum tps codeforce nbsp 長度 題目鏈接:http://codeforces.com/contest/448/problem/C 題目大意:n個1* a [ i ] 的木板,把他們立起來,變成每個木板寬為1長為 a [ i

歸併排序治法

橫向想了一下這幾個經典的排序演算法,個人感覺快排應該是速度最快了,首先快排在空間複雜度的角度應該開銷比歸併要小很多,因為歸併需要申請新的臨時空間,時間複雜度上雖說都是N*log(n)。但是同一個數量級上歸併有很多的陣列複製操作,感覺如果資料很大的話應該比快排所消耗的時間多很多(但是都是在一個數量級上,比如10

[藍橋杯][演算法提高VIP]和大子序列 Java版

題目:對於一個給定的長度為N的整數序列A,它的“子序列”的定義是:A中非空的一段連續的元素(整數)。你要完成的任務是,在所有可能的子序列中,找到一個子序列,該子序列中所有元素的和是最大的(跟其他所有子序列相比)。程式要求你輸出這個最大值。 我們的校賽選了這道題,

Java實現快速排序治法

<span style="font-size:18px;">package com.alibaba; public class QuickSortTest { public stati

演算法設計--眾數和重數問題治法

問題描述: 給定含有n個元素的多重集合S,每個元素在S中出現的次數稱為該元素的重數。多重集S中重數最大的元素稱為眾數。例如,S={1,2,2,2,3,5}。多重集S的眾數是2,其重數為3。對於給定的n

大子陣列問題--治法的思想

國外經典教材《演算法導論》P67頁提到了最大子陣列的問題,書中給出兩種解答方法,分別是暴力求解的方法,分治策略的求解方法。在杭電 ACM OJ 中也有一條類似的題目,連線如下:http://acm.hdu.edu.cn/showproblem.php?pid=1003

3_尋找假幣問題治法

題目 一個袋子裡有30個銀幣,其中一枚是假幣,並且假幣和真幣一模一樣,肉眼很難分辨,目前只知道假幣比真幣重量輕一點。 請問,如何區分出假幣? 分析 首先,分析一下尋找假幣問題,採用遞迴分治的思想求解。 首先為每個銀幣編號,然後將所有的銀幣等分為兩份,

4.1 大子陣列問題(治法)

public class MaxSubArray { //暴力求解 int maxSubArray1(int arr[]) { int max = 0;

冪取模 治法

int pow_mod(int a,int n,int m )       //a^n % m {     if(n == 1) return a % m;     int x = pow_mod(a,n/2,m);     long long ans = (long lo

UVA - 1608 Non-boring sequences治法

name 表示 urn its mes else pac 學習 tro 題目: 如果一個序列的任意連續的子序列中至少有一個只出現一次的元素,則稱這個序列是不無聊的。輸入一個n(n≤200000)個元素的序列A(各個元素均為109以內的非負整數),判斷它是不是不無聊的。 思路

LeetCode 之 Pow(x, n)治法

【問題描述】 Implement pow(x, n). 1.【基礎知識】 1)分治的意識,一道O(N)的演算法題,琢磨出O(lgN)的思想出來就是要求; 2.【屌絲程式碼】 卡殼的地方: 1.Time Limit Exceeded。 #include <vecto

4.1 大子陣列問題(治法)-NlogN

A[low..high]的任何子陣列A[i,j]所處的位置必定是一下三種情況之一: 完全位於子陣列A[low..mid]中,low< =i<=j<=mid 完全位於子陣列A[mid

矩陣相乘治法

一個簡單的分治演算法求矩陣相乘 C=A * B ,假設三個矩陣均為n×n,n為2的冪。可以對其分解為4個n/2×n/2的子矩陣分別遞迴求解: 遞迴分治演算法: 演算法中一個重要的細節就是在分塊的時候,採用的是下標的方式。 #include &