一、分治法的求解過程:
(1)劃分
:既然是分治,當然需要把規模為
n的原問題劃分為
k個規模較小的子問題,並盡量使這
k個子問題的規模大致相同。
(2)求解子問題
:各子問題的解法與原問題的解法通常是相同的,可以用遞迴的方法求解各個子問題,有時遞迴處理也可以用迴圈來實現。
(3)合併
:把各個子問題的解合併起來,合併的代價因情況不同有很大差異,分治演算法的有效性很大程度上依賴於合併的實現。
典型的遞推方程:
迭代法可求得
典型案例:
問題:r是由n
個元素構成的序列集合,
r=,求r的
全排列perm(r)。
問題理解:
(1) 若r
中只有1
個元素,則
perm(r)=(r)
(2) 若r
中只有2
個元素,則
perm(r)=(r
1)perm(r1)
∪(r2)perm(r2)
其中,ri
=r-
(3) 若r
中有3個元素,則
perm(r)=(r
1)perm(r1)
∪(r2)perm(r2)
∪(r3)perm(r3)
分析:
依次將待排列的陣列的後
n-1個元素與第乙個元素交換
,則每次遞迴處理的都是後
n-1個元素的全排列。當陣列元素僅有乙個時為此遞迴演算法的出口。
**展示:
#includeusing namespace std;
void perm(int *arr, int k, int m) //m是陣列最後乙個元素的下標
if((n == 1) || (m == 1))
if(n < m)
if(n == m)
return q(n,m-1) + q(n-m,m);
}int main() 1
、m=s
中各點x
間座標的中位數;
構造s1和s2
; //s1=,
//s2= 2
、cpair2(s1,d1);
cpair2(s2,d2); 3
、dm=min(d1,d2); 4
、設p1是s1
中距垂直分割線
l的距離在
dm之內的所有點組成的集合; p2
是s2中距分割線
l的距離在
dm之內所有點組成的集合; 將
p1和p2中點依其
y座標值排序; 並設
x和y是相應的已排好序的點列; 5
、通過掃瞄
x以及對於
x中每個點檢查
y中與其距離在
dm之內的所有點(最多
6個)可以完成合併; 當
x中的掃瞄指標逐次向上移動時,
y中的掃瞄指標可在寬為
2dm的區間內移動; 設
dl是按這種掃瞄方式找到的點對間的最小距離; 6
、d=min(
dm,dl);
returntrue;}
當k>0
時,將2k×
2k棋盤分割為4個
2k-1×2
k-1子棋盤
(a)所示。
特殊方格必位於
4個較小子棋盤之一中,其餘
3個子棋盤中無特殊方格。為了將這
3個無特殊方格的子棋盤轉化為特殊棋盤,可以用乙個
l型骨牌覆蓋這
3個較小棋盤的會合處,如
(b)所示,從而將原問題轉化為
4個較小規模的棋盤覆蓋問題。遞迴地使用這種分割,直至棋盤簡化為棋盤1×
分治法求最近點對
1 演算法描述 1.分割 將集合s進行以垂直於x軸的直線l進行平均劃分,並且保證sl和sr中的點數目各為n 2,否則以其他方式劃分s,有可能導致sl和sr中點數目乙個為1,乙個為n 1,不利於演算法效率,要盡量保持樹的平衡性 依次找出這兩部分中的最小點對距離 l和 r,記sl和sr中最小點對距離 m...
分治法求最近點對問題
分治法 1 演算法描述 已知集合s中有n個點,分治法的思想就是將s進行拆分,分為2部分求最近點對。演算法每次 選擇一條垂線l,將s拆分左右兩部分為sl和sr l一般取點集s中所有點的中間點的x座標來劃分,這樣可以保證sl和sr中的點數目各為n 2,否則以其他方式劃分s,有 可能導致sl 和sr中點數...
分治法求最近點對問題
1 演算法描述 已知集合s中有n個點,分治法的思想就是將s進行拆分,分為2部分求最近點對。演算法每次 選擇一條垂線l,將s拆分左右兩部分為sl和sr,l一般取點集s中所有點的中間點的x座標來劃分,這樣可以保證sl和sr中的點數目各為n 2,否則以其他方式劃分s,有 可能導致sl 和sr中點數目乙個為...