目錄
知識點1.問題
2.解析
3.設計
4.分析
5.原始碼
1.回溯法摘自[中琦2513]的原創文章
(1)概念
回溯演算法實際上乙個類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就「回溯」返回,嘗試別的路徑。
回溯法是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通就退回再走的技術為回溯法,而滿足回溯條件的某個狀態的點稱為「回溯點」。
許多複雜的,規模較大的問題都可以使用回溯法,有「通用解題方法」的美稱。
(2)基本思想
若用回溯法求問題的所有解時,要回溯到根,且根結點的所有可行的子樹都要已被搜尋遍才結束。
而若使用回溯法求任乙個解時,只要搜尋到問題的乙個解就可以結束。
(3)用回溯法解題的一般步驟
a.針對所給問題,確定問題的解空間: 首先應明確定義問題的解空間,問題的解空間應至少包含問題的乙個(最優)解。
b.確定結點的擴充套件搜尋規則
c.以深度優先方式搜尋解空間,並在搜尋過程中用剪枝函式避免無效搜尋。
圓排列問題:給定n個圓的半徑序列,將它們放到矩形框中,各圓與矩形底邊相切,求具有最小排列長度的圓排列。
問題描述:給定n個大小不等的圓c1,c2,…,cn,現要將這n個圓排進乙個矩形框中,且要求各圓與矩形框的底邊相切。圓排列問題要求從n個圓的所有排列中找出有最小長度的圓排列。例如,當n=5,且所給的5個圓的半徑分別為9,3,2,7,1時,這5個圓的最小長度的圓排列為3,9,2,7,1,如圖所示。
2.1小插曲
剛開始沒搞懂題目啥意思,就去search了一下,然後看到了如下讓我懷疑自己數學的式子
圖1截圖自一篇熱度醬紫的部落格
個人覺得應該把第乙個式子左邊的x^2改為x
2.2解析
圓排列問題的解空間是一棵排列樹,利用回溯演算法來遍歷圓排列問題的每一種解的排列
設r=[r1,r2,……rn]是n個圓的半徑,則相應的解的排列樹由r[1:n]的所有排列組成
陣列x儲存當前圓排列的圓心橫座標
陣列bestr儲存最優圓排列
初始時,r是輸入的n個圓的半徑,計算結束後將r更新為最優解的圓排列
center計算圓在當前圓排列中的橫座標,根據勾股定理由x = sqrt((r1+r2)^2-(r1-r2)^2)推導出x = 2*sqrt(r1*r2)
compute計算當前圓排列的長度,minlen記錄當前最小圓排列長度
在遞迴演算法backtrack中,當i>n時,演算法搜尋至葉節點,得到新的圓排列方案。此時演算法呼叫compute計算當前圓排列的長度,適時更新當前最優值
當i temp)
temp = xvalue;
} return temp;
}//計算圓排列長度
compute()
if (high - low < minlen)
}//回溯演算法
backtrack(int t)
for (int j = t; j < n; ++j)
swap(r[t], r[j]); //不能忘了恢復現場!!
}}如果不考慮計算當前圓排列中各圓的圓心橫座標和計算當前圓排列長度所需的計算時間,則 backtrack需要o(n!)計算時間
由於演算法backtrack在最壞情況下需要計算o(n!)次圓排列長度,每次計算需要o(n)計算時間
從而整個演算法的計算時間複雜性為o((n+1)!)
github位址
演算法分析與設計實踐 大作業 圓排列問題
給定n個圓的半徑序列,將它們放到矩形框中,各圓與矩形底邊相切,求具有最小排列長度的圓排列。圓排列問題的解空間是一棵排列樹。按照回溯法搜尋排列樹的演算法框架,設開始時a r1,r2,rn 是所給的n個元的半徑,則相應的排列樹由a 1 n 的所有排列構成。定義乙個函式center 來計算圓在當前圓排列中...
演算法大作業 圓排列問題
圓排列問題 給定n個圓的半徑序列,將它們放到矩形框中,各圓與矩形底邊相切,求具有最小排列長度的圓排列。首先舉乙個例子,當給定的圓半徑為1,1,3時則可以給出如下排列使排列長度最小 所以這題也算是乙個排列問題,如何排列能夠使排列的長度最小。在排列時有以下幾種情況 1 每個圓相繼相切 如上面的例子裡每個...
演算法大作業 圓排列問題
給定n個大小不等的圓c1,c2,cn,現要將這n個圓排進乙個矩形框中,且要求各圓與矩形框的底邊相切。圓排列問題要求從n個圓的所有排列中找出有最小長度的圓排列。例如,當n 3,且所給的3個圓的半徑分別為1,1,2時,這3個圓的最小長度的圓排列如圖所示。其最小長度為。圓排列問題的解空間是一棵排列樹,按照...