8 3遞迴與分治

2021-06-23 01:47:48 字數 2464 閱讀 2681

1.棋盤覆蓋問題:

分治演算法:

①把棋盤分成四份  ②遞迴解決,當不能再分時返回  ③不用合併,邊遞迴邊打表就行

在乙個 2^k * 2^k 個方格組成的棋盤中,若恰有乙個方格與其它方格不同,則稱該方格為一特殊方格,稱該棋盤為一特殊棋盤。顯然特殊方格在棋盤上出現的位置有 4^k 種情形。因而對任何 k>=0 ,有 4^k 種不同的特殊棋盤。下圖所示的特殊棋盤為 k=2 時 16 個特殊棋盤中的乙個。

在棋盤覆蓋問題中,要用下圖中 4 中不同形態的 l 型骨牌覆蓋乙個給定的特殊棋牌上除特殊方格以外的所有方格,且任何 2 個 l 型骨牌不得重疊覆蓋。易知,在任何乙個 2^k * 2^k 的棋盤中,用到的 l 型骨牌個數恰為 (4^k-1)/3 。

用分治策略,可以設計解棋盤問題的乙個簡捷的演算法。

當 k>0 時,將 2^k * 2^k 棋盤分割為 4 個 2^(k-1) * 2^(k-1) 子棋盤,如下圖所示。

特殊方格必位於 4 個較小子棋盤之一中,其餘 3 個子棋盤中無特殊方格。為了將這 3 個無特殊方格的子棋盤轉化為特殊棋盤,我們可以用乙個 l 型骨牌覆蓋這 3 個較小的棋盤的匯合處,如下圖所示,這 3 個子棋盤上被 l 型骨牌覆蓋的方格就成為該棋盤上的特殊方格,從而將原問題化為 4 個較小規模的棋盤覆蓋問題。遞迴的使用 這種分割,直至棋盤簡化為 1x1 棋盤。

#include //湖南師範大學oj-10432 

#include #includeusing namespace std;

int biao[70][70],now = 1;

void solve(int x1,int x2,int y1,int y2,int xx,int yy)

else

if(xx >= m1 + 1 && xx <= x2 && yy >= y1 && yy <= m2) //在第二個格仔裡

else

if(xx >= x1 && xx <= m1 && yy >= m2 + 1 && yy <= y2) //在第三個格里

else

if(xx >= m1 + 1 && xx <= x2 && yy >= m2 + 1 && yy <= y2) //在第四個格仔裡

now++;

solve(x1,m1,y1,m2,xx1,yy1); //第乙個格仔

solve(x1,m1,m2 + 1,y2,xx3,yy3); //第三個格仔

solve(m1 + 1,x2,y1,m2,xx2,yy2); //第二個格仔

solve(m1 + 1,x2,m2 + 1,y2,xx4,yy4); //第四個格仔

}int main()

printf("\n");}}

return 0;

}

2.迴圈日程表問題:

3.巨人和鬼的問題(好演算法):

演算法分析:

本題屬於凸包問題。

我們設p1..pn為巨人的固定點;pn+1..p2n為鬼的固定點。我們採取分治採取分治策略尋找序列[pp..pr]中的配對方案(初始時[pp..pr]為[p1..p2n]):

在[pp..pr]中找出乙個最低位置(y座標值最小)的乙個點p0,如果這樣的點有多個,則選取最左邊的點為p0,p0與pp交換。然後將其餘點[pp+1..pr]按相對 pp的極角遞增的順序排列。顯然pp與其餘點pp+1..pr之間的任何線段是不會交叉的。我們從pp開始尋找乙個巨人和鬼成對的最小子區間[pp..pi](p≤i≤r)。若該子區間僅剩乙個元素,配對結束;否則巨人(鬼)pp與鬼(巨人)pi配對。這樣使得尚未配對的巨人和鬼分布在兩個子區間[pp+1..pi-1],[pi+1..pr]。繼續按上述分治策略分別遞迴求解[pp+1..pi-1]和[pi+1..pr]。

如上圖,以點p1,將其他點按相對p1的極角遞增排序。然後從p2開始順序地找乙個最短的配對序列p1-p6(鬼和巨人的個數要相等,這樣才能一一配對。p1-p6是3個鬼,3個巨人)。怎樣求分割線p1p6呢?是給鬼和巨人乙個標誌,設鬼為-1,巨人為1,從p2開始找時,逐漸累加,直到為1時停止,表明鬼和人的個數相等,如p1到p2時:2個鬼(-1-1=-2),繼續到p3:2鬼1巨人(-1-1+1=-1),p4:3鬼1巨人(-1-1+1-1=-2),p5:3鬼2巨人(-1-1+1-1+1=-1),p6:3鬼3巨人(-1-1+1-1+1+1=0),此時鬼和巨人的個數相等,則分割線為p1p6,將p1-p8分割成(p2-p5)和(p7-p8)。再遞迴對(p2-p5)和(p7-p8)按同樣的方法分治求解。

分治與遞迴

分治與遞迴 分治法的設計思想是,將乙個難以直接解決的大問題,分割成一些規模較小的相同問題,以便各個擊破,分而治之。對這k個子問題分別求解。如果子問題的規模仍然不夠小,則再劃分為k個子問題,如此遞迴的進行下去,直到問題規模足夠小,很容易求出其解為止。將求出的小規模的問題的解合併為乙個更大規模的問題的解...

遞迴與分治

一 1 求階乘 int factorial int n 2 fibonacci函式 int fibonacci int n 3 全排列 1 字串的全排列 主函式見 2 int permutation char a,int k,int m permutation arr,0,n 1 return 0 ...

遞迴與分治

fibonacci數列 無窮數列1,1,2,3,5,8,13,21,34,55,稱為fibonacci數列。它可以遞迴地定義為 第n個fibonacci數可遞迴地計算如下 int fibonacci int n 編寫完整的主函式,分別記錄利用上述遞迴函式求第47,48,49,50,51,52個fib...