1. 程式人生 > 其它 >一、遞迴與分治策略

一、遞迴與分治策略

一、概述

1.設計思想

遞迴:直接或間接地呼叫自身

分治法:將一個規模為n的難以解決的大問題劃分成k個規模較小的子問題,這些子問題相互獨立且與原問題性質和解法類似,遞迴求解這些子問題,再合併子問題的解得到原問題的解

2.求解過程

(1)劃分(平衡子問題、獨立子問題)

(2)求解子問題(遞迴、迴圈)

(3)合併(對演算法效率影響較大)

二、例題總結

(前面5個問題運用遞迴策略,後面運用分治策略)

1.階乘函式

遞迴定義式:

遞迴實現:

2.Fibonacci數列

歸定義式:

遞迴實現:

演算法改進:避免重複計算,自下而上計算,由f(0)和f(1)算出f(2)...

3.排列生成問題

遞迴關係:

(1)將n個元素看成由兩部分組成:第一部分是第一個元素,第二部分是後面所有元素;

(2)將生成排列過程看作兩步:第一步求所有可能出現在第一個位置的元素,即把第一個元素與後面所有元素交換;第二步固定第一個元素,求後面所有元素的排列。

Perm(R)的遞迴演算法實現:

4.整數劃分問題

將正整數n表示成一系列正整數之和,稱這種表示為正整數n的劃分,稱n的不同劃分個數為正整數n的劃分數,記作p(n)

5.Hanoi塔問題

6.折半查詢

7.大整數乘法(演算法思想>程式碼)

8.Strassen矩陣乘法

9.棋盤覆蓋

棋盤覆蓋問題(board cover problem)要求用4中不同形狀的L型骨牌覆蓋給定棋盤上除特殊方格以外的所有方格,且任何兩個L型骨牌不得重複覆蓋。

分治策略:將棋盤劃分為大小相等的子棋盤,並且每個子棋盤均包含一個特殊方格,從而將原問題分解為規模較小的子問題。具體步驟如下:將2k*2k棋盤劃分為4個2k-1*2k-1子棋盤,特殊方格必位於4個較小子棋盤之一中,其餘3個子棋盤無特殊方格,用一個L型骨牌覆蓋這3個較小棋盤的匯合處,又得到3個具有特殊方格的子棋盤,從而將原問題轉換為4個較小規模的棋盤覆蓋問題。遞迴使用這種分割,直至棋盤簡化為1*1棋盤。

演算法實現:

演算法分析:

10.歸併排序

按記錄在序列中的位置對序列進行劃分,穩定的演算法

演算法思想:

將待排序序列劃分為長度大致相等的兩個子序列,若子序列長度為1,則劃分結束,否則繼續執行劃分,最後得到n個長度為1的有序子序列

不斷進行兩兩合併,用歸併演算法將它們排序;

如此繼續下去,直至得到一個長度為n的有序序列。

演算法實現:設將兩個相鄰有序子序列r[s]~r[m]和r[m+1]~r[t]合併為一個有序序列r1[s]~r1[t],函式Merge實現合併操作。

演算法分析:

11.快速排序

按照記錄的值對序列進行劃分,不穩定的演算法

演算法思想:

演算法實現:

演算法分析:

12.最近點對問題

給定平面上n個點,找其中的一對點,使得在n個點組成的所有點對中,該點對間的距離最小。(只找其中一對最近點即可)

演算法思想:

(1)劃分:將集合S劃分為兩個子集S1和S2,根據平衡子問題原則,每個子集大約包含n/2個點,設最近點對為Pi和Pj,有以下三種情況:

①Pi和Pj均在S1中;

②Pi和Pj均在S2中;

③Pi在S1中,Pj在S2中。

(2)求解子問題:情況①②可遞迴求解:l為S中各點x座標的中位數,垂線x=l將S劃分為S1和S2,遞迴地在S1和S2中求解最近點對問題,得到最近距離d=min{d1,d2};

情況③:設P1是S1中距離垂線l在長度d之內的所有點集,P2是S2中距離垂線l在長度d之內的所有點集;

將P1和P2中的點依其y座標值排序,設p(x,y)是y座標最小的點(P1和P2都有可能);

依次處理P1,P2中的點,在y座標區間[y,y+d]內最多選出8個候選點,計算它們和點p之間的距離,最後得到最近距離d3;

(3)合併:比較d1、d2和d3,選取最小距離作為原問題的解。

演算法實現:

演算法分析:

13.迴圈賽日程表

演算法思想:

演算法實現: