問題:
給定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)時,最大子段和為20。
問題求解:
方法一:列舉
學過程式設計的都會,那就是列舉i和j,求i和a[i]到a[j]之間的和的最大值。
時間複雜度o(n^3)。這顯然是不能接受滴。其實這其中進行了大量的重複計算。
#includeusingnamespace
std;
/*簡單演算法:
**v[0]不儲存資料
**t(n)=o(n^2).
*/int maxsum(int *v,int n,int *besti,int *bestj)}}
return
sum;
}int main(void
)
int r = maxsum(arr,m,&i,&j);
cout
<"
"cout
return0;
}
方法二:分治
考慮能不能有o(n*logn)的演算法呢?當然有了……
如果將給定的序列a[1..n]分成長度相等的兩段a[1..n/2]和a[n/2+1:n],分別求出這兩段的最大欄位和。則該給定序列的最大欄位和有三種情行:
1)和a[1..n/2]的最大欄位和相同。
2)和a[n/2+1:n]的最大欄位和相同。
3)最大欄位和包含兩部分,一部分在中,另一部分在a[n/2+1..n]中。
前兩種情形我們可以用遞迴方法求出,第三種情形可以分別求出兩部分的最大欄位和值再相加(注:a[1..n/2]這部分求最大欄位和要以a[n/2]結束,a[n/2+1..n] 這部分求最大欄位和要以a[n/2+1]開始)。序列的最大欄位和即為這三種情形的最大值。
這種情況下,顯然時間複雜度為o(n*logn)。要是有o(n)的演算法該多好呢?事實上還真有。這自然就是要想到動態規劃了吧!!!
#includeusing namespacestd;/*分治法:
**將a[1n]分成a[1n/2]和a[n/2+1n],則a[1n]的最大欄位和有三種情況:
**(1)a[1n]的最大子段和與a[1n/2]的最大子段和相同
**(2)a[1n]的最大子段和與a[n/2n]的最大子段和相同
**(3)a[1n]的最大子段和為ai++aj,1<=i<=n/2,n/2+1<=j<=n
**t(n)=2t(n/2)+o(n)
**t(n)=o(nlogn)
*/int maxsum_div(int *v,int l,intr)
int s2=0;
int rights=0;
for (k=center+1;k<=r;k++)
sum=s1+s2;
if(sumsum=lsum;
if(sumsum=rsum;
}returnsum;
}int main(void)
int r = maxsum_div(arr,0,m);
coutreturn 0;
}
方法三:動態規劃
動態規劃不太好理解
#includeusing namespacestd;int maxsum_dyn(int *a,intn)
if(temp<0)
}returnmaxn;
}int main(void)
int r =maxsum_dyn(arr,m);
coutreturn 0;
}
分析一下這個演算法,借用了乙個臨時變數temp,其實有三種情況:
1. 若temp>maxn則更新maxn,並儲存開始和結束位置;
2. 若temp<0則令temp = 0,因為temp<0則不可能繼續用temp更新最大值了;
3. 若0(temp的使用時關鍵,好好理解這種思想。理解不了也沒關係,這是比較難想的方法。)
程式設計珠璣上的經典題目,也已經被做爛了,除了最後乙個方法,其他的都是浮雲,但是最後乙個方法寫得也比較囉嗦,k完全沒必要。
int sum(int* a, intn)
return
maxsum;
}
最大子段和 分治與動態規劃
問題 給定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個整數 可能為負數 組成的序列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個整數 可能為負整數 組成的序列a1,a2,a3,a4,a5,an,求該序列子段和的最大值,子段和 定義為連續 下標遞增 的元素之和。當所有的整數均為負整數時定義其最大子段和為0。如序列為時,最大子段和為20。該問題可以用分治法或者動態規劃來求解。下面給出兩種演算法的思路及 實現 思路 ...