圓排列問題

2021-10-07 05:36:10 字數 2379 閱讀 9139

給定n個大小不等的圓c1,c2,…,cn,現要將這n個圓排進乙個矩形框中,且要求各圓與矩形框的底邊相切。圓排列問題要求從n個圓的所有排列中找出有最小長度的圓排列。

例如,當n=3,且所給的3個圓的半徑分別為1,1,2時,這3個圓的最小長度的圓排列如圖所示。其最小長度為2+4√2。

如圖所示,三個圓分別與底線相切排列,但是排列方式不同,排列產生的總長度是不同的。

上面的圖的總長度是小於下面的圖的總長度。圓排列問題是尋求乙個產生最短的長度的圓排列方式。

下面用回溯法的限界思想來解圓排列問題

回溯法介紹參考自回溯法介紹

先介紹一下回溯法

1、基本概念:

回溯法是一種類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就「回溯」返回,嘗試別的路徑。回溯法是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為「回溯點」。

2、基本思想

當所給的問題是確定n個元素滿足某種性質的排列時,相應的解空間樹稱之為排列樹。排序樹通常有**n!**葉結點。

4、回溯法框架

1

void backtrack (

int t)210

}//呼叫函式回溯

在圓排列問題中,我們要做的就是以深度優先方式搜尋解空間,並在搜尋過程中用剪枝函式避免無效搜尋。

實現**主要分為三部分

1、center:求每個圓的圓心橫座標,如圖所示第n個圓的圓心橫座標為與其相切的圓的橫座標+2*√(r[n]*r[n-1])。他可能與前n-1個圓中的任乙個圓相切,所以需要遍歷前n-1個圓求出第n個圓的圓心橫座標。初始化時,第乙個圓的圓心橫座標為0。

2、compute:計算圓排列的長度,變數min表示最小圓排列的長度,通過比較找出最小的左部座標和最大的右部座標,相減後就是該圓排列的長度,然後把每次不同的排列長度相比較,對min進行更新。

3、backtrack:當i>n時,演算法搜尋至葉節點,得到新的圓排列方案。此時演算法呼叫compute計算當前圓排列的長度,適時更新當前最優值。當i核心**

double

center

(int n)

return length;

}

void

compute()

if(high - low < min)

}

void

backtrack

(int t)

swap

(r[t]

, r[i]);

//全排列換回}}

}

時間複雜度由回溯法的排列樹可知,最壞情況下搜尋子結點的時間複雜度是o(n!)次,即全排列的時間複雜度。backtrack()函式每次計算圓排列長度需要o(n)計算時間。所以綜上,整個演算法的計算時間複雜性為o((n+1)!)。

雖然理論上時間複雜度很大,但實際的消耗實際由於增加了剪枝條件,會比o((n+1)!)小很多。

空間複雜度

o(n)

演算法還可以改進的地方

1、1,2,…, n和n,…,2,1這種互為映象的排列具有相同的圓排列長度,只計算乙個就夠了,可以減少約一半的計算量。

2、若所有圓的半徑均相同,則只需要計算乙個就夠了,而不用計算n!個完全相同的圓排列。

圓排列問題

給定n個大小不等的圓 c1,c2,cn,現要將這 n個圓排進乙個矩形框中,且要求各圓與矩形框的底邊相切。圓排列問題要求從 n個圓的所有排列中找出有最小長度的圓排列。例如,當 n 3,且所給的 3個圓的半徑分別為1,1,2時,這 3個圓的最小長度的圓排列如圖所示。其最小長度為 2 4 2 void c...

圓排列問題

給定n個大小不等的圓c1,c2,cn,現要將這n個圓排進乙個矩形框中,且要求各圓與矩形框的底邊相切。圓排列問題要求從n個圓的所有排列中找出有最小長度的圓排列。例如,當n 3,且所給的3個圓的半徑分別為1,1,2時,這3個圓的最小長度的圓排列如圖所示。其最小長度為2 4 2。上述演算法尚有許多改進的餘...

圓排列問題

圓排列問題 給定n個圓的半徑序列,將它們放到矩形框中,各圓與矩形底邊相切,求具有最小排列長度的圓排列。圓的擺放位置不同 先後順序不同 得到的結果可能不同,所以這是乙個排列問題,在回溯裡面需要新增全排列的 要得到圓排列的長度,我們需要知道最右邊圓心的橫座標,它的半徑 第乙個圓的半徑 根據演算法的約定,...