最大m子段和問題演算法進化歷程

2021-07-29 10:15:24 字數 2492 閱讀 7345

/*

name:

author:

date: 23-03-17 08:08

description:

【問題描述】----最大m子段和問題

給定由 n個整數(可能為負整數)組成的序列a1,a2,a3,……,an,以及乙個正整數 m,要求確定序列 a1,a2,a3,……,an的 m個不相交子段,

使這m個子段的總和達到最大,求出最大和。

演算法思路:

經典的動態規劃優化的問題。設f(i, j)表示前i個數劃分成j段,且包括第i個數的最大m子段和,那麼有dp方程:

f(i, j) = max (k = j - 1 ... i - 1) }

也就是說第i個數要麼自己劃到第j段,要麼和前乙個數一起劃到第j段裡面,轉移是o(n)的,總複雜度o(n * n * m)。

演算法1:int maxmsubsum(int i, int j);//自頂向下的備忘錄演算法

設定乙個備忘錄陣列b[m+1][n+1],b[i][j]表示把總長度為j的序列分成i個子段後,這i個子段的總和(其中第i個子段包含元素a[j-1])

利用原問題的遞迴關係,使用遞迴函式來求解。最後遍歷b[m][j],找出最優解。

演算法2:int maxmsubsum_2(int m, int n);//自底向上的動態規劃演算法

從i=1開始,依次記錄每乙個b[i][j],最後獲得最大規模的b[m][n]。

和演算法1一樣,最後遍歷b[m][j],找出最優解。

演算法3:int maxmsubsum_3(int m, int n);//優化的動態規劃演算法

與更早的資料沒有關係,於是可以用兩個一維陣列 maxsum[n+1] 和 cursum[n+1]代替b[m+1][n+1]。

最後寫了乙個函式 void printsubque(int m, int n); //查詢第i段連續子串行的左右邊界,並輸出這些子串行,

該函式需要用到備忘錄陣列b[m+1][n+1],故只能對演算法1和演算法2產生的結果有效。

*/#include#includeusing namespace std;

int maxmsubsum(int i, int j);//自頂向下的備忘錄演算法

int maxmsubsum_2(int m, int n);//自底向上的動態規劃演算法

int maxmsubsum_3(int m, int n);//優化的動態規劃演算法

void printsubque(int m, int n); //查詢第i段連續子串行的左右邊界,並輸出這些子串行

const int inf = -999999; //自定義的無窮小

const int m = 3;

const int n = 7;

int a[n] = ;

//int a[n] = ;

int b[m+1][n+1];

int main(int argc, char **argv)

maxmsubsum(m, n);

// maxmsubsum_2(m, n);

int max = b[m][1];

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

cout << max << endl;

printsubque(m, n);

//max = maxmsubsum_3(m, n);

// cout << max << endl;

system("pause");

return 0;

}int maxmsubsum(int i, int j)//備忘錄演算法

else

} //更新prem[j],為處理下一行做準備

maxsum[i] = cursum[i];

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

// cout << i << ": ";

// for (int j=1; j<=n; j++)

// cout << maxsum[j] << " ";

// cout << endl;

}

return maxsum[n];

} void printsubque(int m, int n)//查詢第i段連續子串行的左右邊界,並輸出這些子串行

; int r[m+1] = ;

int max;

int left, right;

for (int i=m,j=n; i>0; i--,j=left-1)

} left = right; //查詢第i段連續子串行的左邊界

while (b[i][left-1] > b[i-1][left-1] && left > 1)

l[i] = left;

r[i] = right; }

for (int i=1; i<=m; i++) //輸出m段子序列

cout << ")" << endl;

}}

最大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...