链接
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4134
题解
分析样例之后,我假设出这样的算法:
固定第一个点不动,其余的点都移到离自己最近的点。
固定第一个点不动一定是最优解吗?
假设我们已经找到了最优解,且没有任何一个点是不移动的,那么我们可以进行旋转,在这个过程中一定可以使得答案变小或变大、或者不变,这取决于旋转的方向和点的分布,如果顺时针旋转使得答案变小,那么逆时针旋转就会使得答案变大,总之你就能构造出一组更优解,换言之,一开始的假设是不成立的,而当我旋转到某个点和原来的位置重合时(一个点和其他点的原始位置重合也算),就停下,这样就以定能构造出一组更优解。
也就是说,一定存在一组最优解,使得某些点不需要移动。
而由于这个图形具有高度的对称性,你让任何一个点一开始不动都是一样的,因此我们选择最好处理的一号点。
两个点不会移动到同一个地方吗?
不会
假设上述情况存在,如图所示,红色代表目标状态,绿色代表原始状态,首先可以肯定的是两个红点之间最多有一个绿点(因为绿点间的距离一定大于红点间的距离),那么在如图情形下,
b<a,c<d
b
<
a
,
c
<
d
所以
b+c<a+d
b
+
c
<
a
+
d
所以
b+c+b+c<a+b+c+d
b
+
c
+
b
+
c
<
a
+
b
+
c
+
d
所以
2n<2n+m
2
n
<
2
n
+
m
所以
n>n+m
n
>
n
+
m
即
m<0
m
<
0
这显然是不可能的,所以我们一开始的假设就不成立,也就不存在两个点会移动到同一个点的情况
代码
#include <cstdio>
#include <cmath>
#include <algorithm>
#define maxn 2018
using namespace std;
double n, m, pos1[maxn], pos2[maxn];
int main()
{
int i, j;
double ans, t;
while(~scanf("%lf%lf",&n,&m))
{
for(i=1;i<=n;i++)pos1[i]=(i-1)*10000.0/n;
for(i=1;i<=n+m;i++)pos2[i]=(i-1)*10000.0/(n+m);
for(i=1,ans=0.0;i<=n;i++)
{
t=1e100;
for(j=1;j<=n+m;j++)t=min(t,fabs(pos1[i]-pos2[j]));
ans+=t;
}
printf("%.10lf\n",ans);
}
return 0;
}