給定n個圓的半徑序列,將它們放到矩形框中,各圓與矩形底邊相切,求具有最小排列長度的原序列。
一般而言我們會想到這種做法:
但是這種只是其中一種,我們並沒有考慮完全,還有一些如:
小球本來可以放到兩個大球的中間,不增加長度的
這個就類似於最短路的問題,由此我們想到了回溯演算法。
開始時設a=[r1,r2,……rn]是所給的n個元的半徑,則相應的排列樹由a[1:n]的所有排列構成。
cter(x)用來計算第n個圓的橫座標
設:圓1的橫座標是x1,半徑是r1,圓2的橫座標是x2,半徑是r2
**(r1+r2)2-(r1-r2)2=(x1-x2)^2
=>4r1r2=(x1-x2)^2
=>2√(r1r1)=x1-x2
**compute函式計算當前排列長度
dfs為核心函式,便利每一種可能
結果#include
#include
#include
using
namespace std;
const
int n =
100;
const
int inf =
0x3f3f3f3f
;double minn = inf,x[n]
, r[n]
;//分別為最小圓排列長度,每個圓心橫座標,每個圓半徑
int n;
double bestr[n]
;//最小圓排列的半徑順序
double
cter
(int n)
return temp;
}void
compute()
if(high-low
}void
dfs(
int t)
else
swap
(r[t]
, r[j]);
//還原}}
}int
main()
dfs(1)
;printf
("最小圓排列長度為:%.2f\n"
, minn)
;printf
("最小圓排列的順序對應的半徑分別為:\n");
for(
int i =
1; i <= n;
++i)
return0;
}

最壞情況下會遍歷所有的解空間序列,此時的時間複雜度為o(n!)
每次排列都需要呼叫一次compute函式,時間複雜度為o(n)
綜上,該演算法的時間複雜度為o((n+1)!)
演算法分析與設計實踐大作業
圓排列問題 給定n個圓的半徑序列,將它們放到矩形框中,各圓與矩形底邊相切,求具有最小排列長度的圓排列。首先,已知圓的個數n以及記錄各圓半徑的陣列r i i 1 n 記錄各圓圓心橫座標的陣列x i i 1 n。要記錄最短排列長度minlen,最終求出排列順序。要注意,只要大小合適,目標圓就有可能與排列...
演算法分析與實踐 大作業 圓排序問題
圓排列問題 給定n個圓的半徑序列,將它們放到矩形框中,各圓與矩形底邊相切,求具有最小排列長度的圓排列。圓排列問題主要用到了回溯法。問題的解空間是一棵排列數。按照回溯法遍歷每種排列,求得最小排列長度的最優解。變數n為圓的個數 陣列r n 儲存每個圓的半徑,x n 儲存每個圓的圓心座標,bestr n ...
演算法分析與設計實踐 大作業 圓排列問題
給定n個圓的半徑序列,將它們放到矩形框中,各圓與矩形底邊相切,求具有最小排列長度的圓排列。圓排列問題的解空間是一棵排列樹。按照回溯法搜尋排列樹的演算法框架,設開始時a r1,r2,rn 是所給的n個元的半徑,則相應的排列樹由a 1 n 的所有排列構成。定義乙個函式center 來計算圓在當前圓排列中...