LA 3708 Graveyard

题目链接:

https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1709

题意:

一个周长为10000的圆上等距离分布n个点,新增加m个点, 若使所有 m+n 个点等距离的分布在圆上,求原来n个点的最小移动距离。

分析:

看下样例,很容易想到是固定一个点不动,移动剩下 n1 个点,就是说以这个不动点为原点,顺时针放剩下的 n+m1 个点。
起初想啊,算出每个点的距离之后,把这 n1 个点跟他相邻的点都比较一下找个最近的点,后来看了白书的做法, zz选手表示还是觉得很巧妙的。。
他的思想是将这个圆分成 n+m 份,这样最后的 n+m 个点就分别占据着圆上的整数点,我们可以求出原始 n 个点的新坐标,这样距离他最近的整数点就是 floor(x+0.5) ,把差累加即可。
但是这样会不会出现两个原始点对应同一个整数点呢?只有当两个数的差小于1的时候他们的 floor(x+0.5) 才有可能相等,但是由于我们把n个点均等的放在了 n+m 的坐标系中,所以任何两个点的距离肯定是大于1的。
最后把坐标还原回来即可。

代码:

/************************************************************************* > File Name: la3708.cpp > Author: jiangyuzhu > Mail: [email protected] > Created Time: Sat 18 Jun 2016 03:22:49 PM CST ************************************************************************/

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<stack>
using namespace std;
typedef pair<int, int>p;
const int maxn = 1e3, mod = 1e9 + 7, oo = 0x3f3f3f3f;
int main (void)
{
    int n, m;
    while(~scanf("%d%d", &n, &m)){
        double ans = 0;
        for(int i = 1; i < n; i++){
            double pos = (double)i / n * (n + m);
            ans += fabs(pos - floor(pos + 0.5));
        }
        ans = ans / (n + m) * 10000;
        printf("%.4f\n", ans);      
    }
}

你可能感兴趣的:(LA 3708 Graveyard)