分治法 全排列 整數劃分 最近點對問題 棋盤覆蓋

2021-09-12 14:33:58 字數 2364 閱讀 9927

一、分治法的求解過程:

(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中點數目乙個為...