書上講解 最大m段子段和問題

2022-05-20 19:55:24 字數 1188 閱讀 9372

描述

【題解】

設f[i][j]表示前i個數字分成了j段的最大子段和。

則f[i][j] = max(f[i-1][j]+a[i] (第i個數字和第j段合在一起),f[k][j-1]+a[i] (第i個數字作為第j段的第乙個數字,同時在j-1段的情況中找到和最大的那個))

這樣的時間複雜度是$o(m*n^2)$的,**的寫法在**1中

接下來我們做一些優化。

首先把陣列的第二維改成滾動陣列。

然後令f[i][j]=max(f[1..i][j]);

這樣在做第二層的轉移的時候f[i][j]就能直接用f[i-1][j-1]做轉移了

當然也不用非得再重開乙個新的陣列。

在f[i][j]做完轉移之後把它改成字首的最大值就行。(注意一定要做完轉移之後再改變,因為f[i][j]在轉移的時候用到了f[i-1][j])

這樣在做轉移的時候就少掉了o(n)的一次列舉了

複雜度變成o(n*m)的了.詳見**2

【**1】

#include #include using namespace std;

const int n = 1e6;

const int m = 30;

int f[n+10][m+10],a[n+10];

int n,m;

int main()else}}

int ans = f[m][m];

for (int i = m+1;i <= n;i++) ans = max(ans,f[i][m]);

printf("%d\n",ans);

}return 0;

}

【**2】

#include #include #include using namespace std;

const int n = 1e6;

const int m = 30;

int f[n+10][2],a[n+10];

int n,m;

int main()else

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

f[i][l&1] = max(f[i][l&1],f[i-1][l&1]);

}printf("%d\n",f[n][m&1]);

}return 0;

}

最大m子段和問題

最大m子段和問題 給定由n個整數 可能為負數 組成的序列a1,a2 an 以及乙個正整數m,要求確定a1,a2 an 的m個不相交子段,使m個子段和達到最大。設b i,j 表示陣列a的前j項中i個子段的和的最大值,且第i個子段含a j 1 i m,i j n 則所求最優值為 與最大子段和問題類似,計...

最大m子段和

最大m子段和問題 給定由n個整數 可能為負 組成的序列a1 a2 a3.an,以及乙個正整數m,要求確定序列的m個不想交子段,使這m個子段的總和最大!設b i,j 表示陣列a的前j項中i個子段和的最大值,並且第i個子段包含a j 1 i m,i j n 則所求的最優值為maxb m,j m j n ...

最大m子段和

51nod 1052 題意描述 給定陣列a,長度為n。給定整數m,求不相交的m段字段和的最大值。當m 1 時 該問題就是最大子段和問題。設dp i 為以a i 結尾的最大子段和,當我們考慮dp i 的時候如果dp i 1 0那麼肯定把a i 接在後面最優,否則,取a i 最優。得到 dp i max...