最大子段和問題(maximum interval sum)
一.問題描述
給定長度為n的整數序列,a[1...n], 求[1,n]某個子區間[i , j]使得a[i]+…+a[j]和最大.或者求出最大的這個和.例如(-2,11,-4,13,-5,2)的最大子段和為20,所求子區間為[2,4]。
二.演算法分析
1.窮舉法
1int start = 0;//
起始位置
2int end = 0; //
結束位置
3int max = 0;4
for(int i = 1; i <= n; ++i)517
}18 }
換一種窮舉思路,對於起點 i,我們遍歷所有長度為1,2,…,n-i+1的子區間和,以求得和最大的乙個.這樣也遍歷了所有的起點的不同長度的子區間,同時,對於相同起點的不同長度的子區間,可以利用前面的計算結果來計算後面的。就像傳遞陣列引數時往往傳的不是起止位置,而是起始位置和長度。
1int start = 0;//
起始位置
2int end = 0;//
結束位置
3int max = 0;4
for(int i = 1; i <= n; ++i)516
}17 }
2.分治法
求子區間及最大和,從結構上是非常適合分治法的,因為所有子區間[start, end]只可能有以下三種可能性:
1.在[1, n/2]這個區域內
2.在[n/2+1, n]這個區域內
3.起點位於[1,n/2],終點位於[n/2+1,n]內
以上三種情形的最大者,即為所求. 前兩種情形符合子問題遞迴特性,所以遞迴可以求出. 對於第三種情形,則必然包括了n/2和n/2+1兩個位置,這樣就可以利用第二種窮舉的思路分別向左右擴張求出:
1int maxinterval(int *a, int left, int
right)
217 sum = 0;18
int right_max = 0;19
for(int i = center+1; i <= right; ++i)
2025
int res = left_max+right_max;
26if(res 27 res =leftmaxinterval;
28if(res 29 res =rightmaxinterval;
30return
res;
31 }
3.動態規劃並擴充套件到二維空間
令b[j]表示以位置 j 為終點的所有子區間中和最大的乙個
子問題:如j為終點的最大子區間包含了位置j-1,則以j-1為終點的最大子區間必然包括在其中
如果b[j-1] >0, 那麼顯然b[j] = b[j-1] + a[j],用之前最大的乙個加上a[j]即可,因為a[j]必須包含
如果b[j-1]<=0,那麼b[j] = a[j] ,因為既然最大,前面的負數必然不能使你更大
1 #include2 #include3int a[101][101],b[101],c[101];4
int subsequencesum(int a,intn)5
30return
maxsum;
31}
32int
main()
3351 ans=subsequencesum(b,n);//
算的是兩列間的和,
52if(temp53 temp=ans;54}
55}56 printf("
%d\n
",temp);57}
58//
while(1);
59return0;
60 }
最大子段和問題分析
問題 給定n個整數 可能為負數 組成的序列a 1 a 2 a 3 a n 求該序列如a i a i 1 a j 的子段和的最大值。當所給的整均為負數時定義子段和為0,依此定義,所求的最優值為 max,1 i j n 例如,當 a1,a2,a3,a4,a4,a6 2,11,4,13,5,2 時,最大子...
演算法設計與分析 最大子段和問題
給定由 n個整數組成的序列 求該序列形如 1 分別用蠻力法 分治法和動態規劃法設計最大子段和問題的演算法 2 比較不同演算法的時間效能 3 給出測試資料,寫出程式文件。實驗2.1最大欄位和問題.cpp 此檔案包含 main 函式。程式執行將在此處開始並結束。include using namespa...
最大子段和
設a 是n個整數的序列,稱為該序列的子串行,其中1 i j n.子串行的元素之和稱為a的子段和.例如,a 2,11,4,13,5,2 那麼它的子段和是 長度為1的子段和 2,11,4,13,5,2 長度為2的子段和 9,7,9,8,7 長度為3的子段和 5,20,4,6 長度為4的子段和 18,15...