最大子段和問題及其推廣

2022-08-09 06:27:17 字數 2569 閱讀 6524

實在是太頹廢了,所以開始寫點東西吧。。。。

最大子段和: 給定n個數(可能為負整數)組成的序列a1...an,求該序列形如∑ak(i<=k<=j)的子段和的最大值。當所有整數均為負整數時定義其最大的子段和為0.

依據題意我們可以確定 最優值為max(0,max∑ak(i<=i<=j<=n)); 若我們令b[j] = max∑ak(1<=i<=j)是從序列a的第i個數到第j個數的最大和,那麼我們最後的答案就是找出b陣列裡面記錄的最大的那個值就是答案。由b[j]的定義可以知道b[j-1]>0時,b[j] = b[j-1]+a[j]否則b[j] = a[j];由此得出遞推式b[j] = max(b[j-1]+a[j],a[j]) (1<=j<=n)

**如下

1

int maxsum1(int n,int *a)29

return

sum;

10 }

view code

最大子段和的推廣

(1)最大子矩陣:給定乙個m行n列的整數矩陣a,求其元素和最大的子矩陣

很明顯最大子矩陣和的問題是最大子段和的問題向二維的推廣,我們用陣列a[1:m][1:n]表示給定的矩陣a 其子陣列a[i1:i2][j1:j2]表示左上角和右下角的行列座標分別為(i1,j1)(i2,j2)的子矩陣 其個各個元素之和 記為 s(i1,i2,j1,j2)= ∑∑a[i][j] (i1<=i<=i2,j1<=j<=j2) 那麼ans = max s(i1,i2,j1,j2) (1<=i1<=i2<=m,1<=j1<=j2<=n)

我們可以令t(i1,i2) = maxs(i1,i2,j1,j2)(i<=j1<=j2<=n) = max∑∑a[i][j] 同樣我們令b[j] = ∑a[i][j](i1<=i<=i2) 於是 t(i1,i2) = max∑b[j](1<=j1<=j2<=n) 這又回到了一維的情況於是我們可以得到如下**

1

int maxsum2(int m,int n,int a[105][105

] )212}

13return

sum ;

14 }

view code

最大子矩陣在poj上面有原題目 題號是1050 **如下

#include #include 

#include

using

namespace

std;

const

int m = 105

;int

a[m][m];

int maxsum1(int n,int *a)

return

sum;

}int maxsum2(int m,int n,int a[105][105

] ) }

return

sum ;

}int

main()

printf(

"%d\n

",maxsum2(n,n,a));

return0;

}

view code

2 最大m子段和

最大子段和是最大m子段和的特殊情況即m = 1時的解,我們用b(i,j)表示陣列a的前j項中i個子段和的最大值 那麼很容易得到如下狀態轉移方程 b(i,j) = max(b(i,j-1),max(b(i-1,t))+a[j] 第乙個狀態表示第i個子段包含a[j],而第二個狀態表示第i個子段只包含a[j] 於是很容易得到如下**

1

intmaxsum()211

12}13else

14 b[i][j] = b[i-1][j-1] +a[j];

1516}17

}18int sum = 0;19

for(int j=m;j<=n;j++)

22return

sum ;

23 }

view code

上述演算法顯然需要o(mn^2)但是我們注意到 對b[i][j] 只用到了 第i-1行和第i行因此只要記錄這兩個值就可以,另一方面max(b(i-1,t))的值可以在計算第i-1行是預先計算出來

於是得到優化後的**如下

int

dp()

c[i+n-m] =tmp;

}printf(

"%d\n

",c[n]);

}

view code

最大m子段和問題在杭電oj上有原題 題號是1024 

ac**如下

#include #include 

#include

using

namespace

std;

const

int m = 1000005

;int

n,m;

inta[m];

intb[m],c[m];

intdp()

c[i+n-m] =tmp;

}printf(

"%d\n

",c[n]);

}int

main ()

return0;

}

view code

最大子段和問題

給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整均為負數時定義子段和為0 分治法 分析 首先將陣列分為兩部分,最大子段和 可以在陣列的左半部分也可以在右半部分,也可以橫跨分割點,因此我們只需要用分治思想求出左邊最大...

最大子段和問題

給定n 個整數 有可能是負數 組成的序列,要求分別用蠻力法,減治法和動態規劃法,求最該序列的最大子段和,並對它們的效率進行比較分析。也稱窮舉法或列舉法,是一種簡單直接地解決問題的方法,常常基於問題的描述,所以,蠻力法也是最容易應用的方法。它依賴的基本技術是遍歷,採用一定的策略依次處理待求解問題的所有...

最大子段和問題

問題描述 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如 a i a i 1 a j 當所給的整數均為負數時定義子段和為0.如果序列中全部是負數則 最大子段和為0,依次所定義 所求的最優值max,1 i問題解析 動態規劃演算法 dp i 包含元素i的子段和 dp 0 ...