最大子段和是指,對於一段數列來講,有區間\([l,r]\)使得\(a_i+a_{i+1}+...a_r\)最大,這個最大的和被稱爲最大子段和。php
擴展內容是求解最大子矩陣和。ios
經過枚舉l和r,來枚舉全部可能的狀況,暴力計算l到r的全部和。c++
代碼:算法
for(int i=1;i<=n;i++) for(int j=i;j<=n;j++){ int sum=0; for(int k=i;k<=j;k++) sum+=a[k]; maxx=Max(maxx,sum); }
時間複雜度\(O(n^3)\)數組
咱們能夠發現,其實在計算若干個數的和時,有重複計算,咱們能夠提早預處理前綴和來避免這個問題,優化時間複雜度。優化
代碼:spa
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i]; for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) maxx=Max(maxx,sum[j]-sum[i-1]);
時間複雜度\(O(n^2)\)code
這個問題能夠經過動態規劃來解決。get
咱們發現,若是在咱們已經知道以i結尾的最大子段和,那麼下一步的決策只有兩個:string
咱們設\(f_i\) 表示以i結尾的最大子段和。
狀態轉移:\(f_i=max(f_{i-1}+a_i,a_i)\)
最終答案爲:\(max(f[i]),i=1,2,...n\)
能夠發現,狀態\(f_i\)已經包括了全部的狀態空間,因此最終答案合法。
代碼:
for(int i=1;i<=n;i++) f[i]=Max(f[i-1]+a[i],a[i]); for(int i=1;i<=n;i++) maxx=Max(maxx,f[i]);
時間複雜度:\(O(n)\)
最大子矩陣和問題 http://ybt.ssoier.cn:8088/problem_show.php?pid=1282
思路:咱們枚舉兩行:\(l,r\),並把l到r之間的全部數,壓成一個一維數組,即\(c_i=\sum ^r_{j=l} a_{j,i}\),跑一遍最大字段和,對全部結果取max。
代碼:
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<sstream> #include<queue> #include<map> #include<vector> #include<set> #include<deque> #include<cstdlib> #include<ctime> #define dd double #define ll long long #define ull unsigned long long #define N 101 #define M number using namespace std; const int INF=0x3f3f3f3f; int n,a[N][N],sum[N][N],b[N],f[N],maxx=-INF; inline int Max(int a,int b){ return a>b?a:b; } int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ scanf("%d",&a[i][j]); sum[i][j]=sum[i-1][j]+a[i][j]; } for(int i=1;i<=n;i++) for(int j=i;j<=n;j++){ for(int k=1;k<=n;k++) b[k]=sum[j][k]-sum[i-1][k]; for(int k=1;k<=n;k++){ f[k]=Max(f[k-1]+b[k],b[k]); maxx=Max(maxx,f[k]); } } printf("%d",maxx); return 0; }