1. 程式人生 > >Python “最短”挑戰(12.22)

Python “最短”挑戰(12.22)

Description

有一組點均勻地分佈在在一個周長為10000米的圓上。現在要再新增一些點進去,使得這些點仍均勻分佈。如果僅可以沿圓周移動某些點,請你求總移動距離的最小值。

Input

有多行輸入,每行兩個數字n,m(2<=n<=1000,1<=m<=1000),空格隔開,分別表示原先和要新增的點的數量,當輸入0 0時,表示輸入結束,程式退出。

Output

總移動距離的最小值,保留4位小數。
其餘要求同首題

Sample Input

2 1
2 3
0 0

Sample Output

1666.6667
1000.0000

Reference code

[n1,n2]=list(map(int,input().split(' ')))
while n1 and n2:
    print('%.4f'%sum(abs(i*10000/n1-(i+int(i*n2/n1+0.5))*10000/(n1+n2)) for i in range(n1)))
    [n1,n2]=list(map(int,input().split(' ')))
'''
while True:
    [n1,n2]=list(map(int,input().split(' ')))
    if n1==0 and n2==0:
        break
    ans=0
    x=[i*10000/n1 for i in range(n1)]
    y=[i*10000/(n1+n2) for i in range(n1+n2)]
    for i in range(n1):
        for j in range(n1+n2):
            if y[j]<=x[i]<=y[j+1]:
                ans+=min(x[i]-y[j],y[j+1]-x[i])
    print('%.4f'%ans)
'''

Algorithm Explain

這是一條略有難度的題目,其中的演算法在數學上證明需要一點功夫。筆者在這裡貼一下自己的解法:
我們將這個圓以其中一點為原點展開成一條線段,線段的左端點放點,右端點不放點。
x i x_i 表示原來各點的座標,有
x

i = l i n 1 , 0 i n 1 , i Z , l = 10000 x_i=l \frac{i}{n_1} , 0 \leqslant i \leqslant n_1 , i \in \mathbb{Z} ,l=10000

y j y_j 表示之後各點的座標,有
y j = l j n 1 + n 2 , 0 j n 1 + n 2 , j Z y_j=l \frac{j}{n_1+n_2} , 0 \leqslant j \leqslant n_1+n_2 , j \in \mathbb{Z}

則有
x i y j = l ( i n 1 j n 1 + n 2 ) x_i - y_j=l \left(\frac{i}{n_1}-\frac{j}{n_1+n_2} \right)

要使每一個 i i x i y j \vert x_i-y_j \vert 最小,則 j j 一定滿足以下兩種情況之一:
{ x i y j 0 x i y j + 1 0 \left\{ \begin{aligned} x_i - y_j \geqslant 0 \\ x_i - y_{j+1} \leqslant 0 \end{aligned} \right. ①

{ x i y j 1 0 x i y j 0 \left\{ \begin{aligned} x_i - y_{j-1} \geqslant 0 \\ x_i - y_{j} \leqslant 0 \end{aligned} \right. ②

解①得:
j = i + [ n 2 n 1 i ] j=i+\left[ \frac{n_2}{n_1}i \right]

解②得:
j = i + [ n 2 n 1 i ] + 1 j=i+\left[ \frac{n_2}{n_1}i \right] +1

x i y j y j + 1 x i x_i - y_{j} \leqslant y_{j+1} - x_i 時取①,否則取②,此時有:
{ n 2 n 1 i } 1 2 \left\{ \frac{n_2}{n_1}i \right\}\leqslant \frac{1}{2}

則可以得出,對於每一個 i i ,其對應的 j j 為:
j = i + [ n 2 n 1 i ] + [ { n 2 n 1 i } + 1 2 ] =