在一個周長爲10000的圓上等距分佈着n個雕塑。如今又有m個新雕塑加入(位置能夠隨意放),但願全部n+m個雕塑在圓周上均勻分佈。這就須要移動其中一些原有的雕塑。要求n個雕塑移動的總距離儘可能小。算法
2<=n<=1000, 1<=m<=1000,輸出最小總距離,精確到10-4函數
這題是《算法競賽入門經典--訓練指南》第七頁的一道例題,做者分析的時候聲稱必定有一個雕塑沒有移動,可是沒給出證實spa
我也無法給出證實,由於裏面涉及到round(返回最接近的整數)這種非線性函數,有點難處理code
可是我想到能夠用Matlab畫個圖驗證一下是否是這樣,其實只要肯定舊的n個點中的一個點在新的n+m個點構成的環上的位置,其他的點就都肯定了,咱們隨便找一個點,讓它在一個區間上移動,算出其在各個位置處對應的總距離。我預計這個圖多是中間凹,兩邊高,實際上並不是如此,而是有不少峯。blog
在這個圖中,n=7(注意到圖中恰有7個峯),m=32,區間被分紅1000份。峯的個數彷佛是n/gcd(n,m),對n=8,m=32和n=6,m=2都成立,可是對n=8,m=18就不成立(沒有峯),我表示搞不懂,概括不出這個公式……ci
因此,從圖中可見,讓該點處於區間一端確實可使得總距離最小,可是這個點還有其餘位置能夠放,如上圖中區間中部的6個最低點。(可是做者聲稱的必定有一個雕塑沒移動,貌似也是對的)get
Matlab代碼以下:io
%uva online judge LA 3708, test, <算法競賽入門經典訓練指南>第7頁 n = 7;%original points on a circle m = 32;% points to be added dist = (n + m) / n; step = 0.001; total = zeros(1, 1 / step + 1); t_idx = 0; for start = 0 : step : 1 t_idx = t_idx + 1; for idx = 0 : n - 1 point = start + idx * dist; total(t_idx) = total(t_idx) + abs(point - round(point)); end end plot(total) %此圖與m無關,只與n有關
另外還畫了一個在取定一個雕塑不動的狀況下,總距離隨m,n變化的3D圖:入門
代碼以下:
%uva online judge LA 3708, test2, <算法競賽入門經典訓練指南>第7頁 %假設圈長爲1,爲計算方便,先假設圈長爲n+m,而後再縮放一下 %n = 7;%original points on a circle %m = 8;% points to be added MAX = 30;%max test points for n total = zeros(MAX, MAX); start = 0; for n = 1:MAX for m = 1 : MAX dist = (n + m) / n; for idx = 0 : n - 1 point = start + idx * dist; total(n,m) = total(n,m) + abs(point - round(point)); end total(n,m) = total(n,m) / (m + n); end end figure, mesh(total)