UVALive.3708 Graveyard (思维题)

UVALive.3708 Graveyard (思维题)

题意分析

这标题真悲伤,墓地。
在周长为1e4的圆周上等距分布着n个雕塑,现在要加入进来m个雕塑,最终还要使得这n+m个雕塑等距,那么原来的n个雕塑移动的最小距离是多少。

W=W 依旧没思路,看了题解学习此种技巧。

首先原先给出的n个雕塑中有一个假定不动。然后剩余的n-1的个雕塑移动到最近的目标点。目标点的定义如下:
将原圆周等距分为n+m份,每一份的分界点为一个位置,即目标点。那么难点就在于如何判断是最近的呢,这里用到的方法就是按比例扩大+下取整

刚才说过分为n+m份,那么我们规定那个不动的雕像为0,其他的目标点,依次标记为1,2,3……(n+m-1)。然后按照这样的比例,标记出原先的n个点的位置。这样的标记实际上已经完成了比例的放大,放大比为原来:现在 = 1:(n+m).

放大完成后,我们只需要求出原来和现在的位置差多少就行了:
原来第i个雕塑的位置为
pos = i / n * (n+m) ps:要放大n+m倍
然后要移动到的目标点是 floor(pos + 0.5 )
这两者差的绝对值,就是需要在圆周上移动的比例,注意这里是比例,不是实际的距离,也就是说最后在输出的时候还需要乘1e4.

为何+0.5在下取整就是目标点呢?
不放假设,有一个雕塑在1.01, 其+0.5后为1.51, 下取整完为1,即离它最近的应该是1那个目标点;在比如说有一个雕塑在1.49,+0.5后为1.99,离它最近的也是1那个目标点,而不是2. 不难看出+0.5在下取整是求最近的目标点。

最后,将求出的比例累加,再乘1e4输出即可,注意保留4位小数。

代码总览

#include <cstdio>
#include <cmath>
using namespace std;
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m) != EOF){
        double pos = 0,ans = 0;
        for(int i =1; i<n; ++i){
           pos = 1.0*i/n *(n+m); ans += fabs(pos -floor(pos+0.5))/(n+m);}
        printf("%.4f
",ans*10000);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/pengwill/p/7367131.html