今天參加了一場洛谷網的比賽, 深受打擊. 寒假過了這麼多天, 一直沒有認真學習演算法, 以至於現在的水平比兩個月前還要低.
本來就沒有多少底子, 又退步了許多, 感慨萬分.
在洛谷上看到這麼一道題
最大子段和
如果資料小的話,用暴力列舉很簡單就可以做出來了, 時間按複雜度位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...