最大子段和 三種方法

2021-08-15 13:20:31 字數 2856 閱讀 3754

今天參加了一場洛谷網的比賽, 深受打擊. 寒假過了這麼多天, 一直沒有認真學習演算法, 以至於現在的水平比兩個月前還要低.

本來就沒有多少底子, 又退步了許多, 感慨萬分.

在洛谷上看到這麼一道題

最大子段和

如果資料小的話,用暴力列舉很簡單就可以做出來了, 時間按複雜度位o(n^3)

可是一道演算法題怎麼會這麼簡單呢?

樣例的資料是非常大的, 所以用n^3的辦法乙個樣例都過不了

#include 

#include

using

namespace

std;

int main()

for( int i = 1; i <= n; ++ i )

//cout << "sum = " << sum << endl;

max = max(max, sum);

//cout << max << endl;}}

cout

<< max;

}

稍微優化一下, 使用字首和以及差分, 可以有效地將複雜度降為o(n^2), 可是, 對於這道題來說, 這個時間還是太多了. 只能通過40%的樣例

#include 

#include

#include

long

long

int n, num[220000], qz[220000] = {}, ans = -1e9;

using

namespace

std;

int main()

for( int i = 1; i <= n; ++i )

for( int i = 1; i <= n; ++i )

}cout

<< ans << endl;

}

還有一種分治的方法做這道題, 時間複雜度為o(nlogn), 有點複雜,我還不會.

最簡單的呢,使用dp的方法, 時間複雜度為o(n)

這種方法憑我自己現在的水平是想不出來的, 尤其是現在狀態如此之差. 看別人解釋後寫了**覺得如此巧妙, 於是又驚嘆演算法之神奇

可憐的是, 即便別人告訴我這道題用dp解最簡單, 我也解不出來, 誰叫我dp還沒入門呢?

思路描述是這樣的:

a陣列是儲存輸入的數值;c[i]表示的是a陣列從頭加到i的和;b[i]表示的是從頭到i包括i的的最大子段和~(必須包括i!!!);minn儲存最小的字首和(因為要減去所以要盡量小,詳情見下一行) 動態轉移方程式:b[i]=c[i]-minn(總和減去字首和) 最後輸出b陣列最大的值(題目求最大的子段和)

第一階段的**是這樣的

#include 

#include

#include

using

namespace

std;

long

long

int qz[220000] = {}, num[220000], mm[220000] = {}, an[220000], ans = -1e9;

int main()

cout

<< ans;

}

時間複雜度確實是小, 但是有乙個問題就是空間複雜度太大了, 沒必要這樣開陣列.

看了別人的題解, dalao們用的是滾動陣列, 乙個上面220000的陣列只用兩個元素迴圈滾動即可.

嘆服!妙哉!

#include 

#include

#include

using

namespace

std;

long

long

int qz[2] = {}, mm[2] = {}, ans = -1e9, m, n;

int main()

cout

<< ans;

}

寫這道題還發現了或者說學到了或者說鞏固了幾個小知識

1) 取消cin的同步用這樣的**

std:

:ios

::sync_with_stdio(false);

此為鞏固

2) 使用scanf輸入c++ 中long long 型的數

是這樣的

long

long

int n;

scanf("%lld", &n);

如果n的型別寫為long long dev會發出警告, 還不知道為什麼

3) 使用scanf要包含標頭檔案cstdio

以前我是不包含的, 不過這次在洛谷上提交出現了編譯錯誤, 這也算是發現了自己的乙個小bug吧

___________2018-7-9補充更新___________

今天程式設計訓練測試出了這道題, 時隔多月再次寫這道入門dp, 發現實現方法略有不同.

#include 

#include

#include

using

namespace

std;

const

int inf = 0x3f3f3f3f;

int main()

int qz = 0, max = -inf;

for (int i = 0; i < v.size(); ++i)

}cout

<< max;

}

最大子段和(三)

最大子段和問題 解法三 演算法分析 對於序列a,設j代表當前序列的終點,i代表當前序列的起點 分析 如果a i 是負的,那麼它不可能是最大子段的起點,因為任何包含a i 為起點的子段都可以通過 用a i 1 為起點而得到改進。類似的,任何負的子段都不可能是最優子段的字首 原理相同 如果在迴圈中檢測到...

用三種方法實現最大子列和的求解(Python實現)

問題描述 給定n個整數的序列,求該序列的最大子列和。作業系統 windows 10 編譯環境 pycharm 程式語言 python3.6實現思路 首先得有資料,所以先用 實現隨機列表的生成,隨後用三種演算法實現,並在主函式中實現函式的呼叫以及結果的輸出import random 生成隨機列表 st...

(三)最大子段和問題

1.概念 求陣列的和最大的非空連續子陣列,這樣的連續的子陣列稱為最大子陣列 maximum subarray 2.常規方法 o 3 最大子段和問題 o 3 include using namespace std 列印陣列 void printarray int arr,int strat,int l...