LA3708墓地雕塑

题目链接:点击这里

思路

首先注意审题,题目说的是新加入的 m m 个雕塑可以放在任意位置,因此我们将新加入的雕塑就放在需要的地方(等间隔),只考虑之前的 n n 个雕塑的移动位置。由于周长已经确定,我们可以这样想:先把原有的 n n 个雕塑放在离其最近的新位置上,其余位置摆放新的雕塑,就可以得到移动总距离最小。

实现

因此我们很容易可以写出代码如下:

#include 
#include 

using namespace std;

int n,m;
double circle = 10000;

int main()
{
    while (scanf("%d%d",&n,&m)==2)
    {
        int sum = n+m;
        double ans = 0;
        double each  = circle/sum; //新的间隔
        double origin = circle/n;  //之前的间隔,一定大于新间隔
        for (int i =1 ;i < n;i++)
        {
            double position = origin*i;
            for (int j = 1;j < sum;j++)  //计算离第i个雕塑最近的位置
            {
                if (position == j*each)
                    break;
                double temp1 = (j-1)*each;
                double temp2 = j*each;
                if (position >  temp1 && position < temp2)
                {
                    ans += min(position - temp1,temp2 - position);
                    break;
                }
            }
        }
        printf("%.4f\n",ans);
    }
    return 0;
}

简化代码

读者可以看出,上面的代码较繁琐,因为我们每次去找第 i i 个雕塑的最适位置时都是用的一个for循环,代码复杂度为 O(nm) O ( n ∗ m ) ,实在是太高。
书上有一种很巧妙的思路:先把圆看成是单位圆,利用通分的思想找出离第 i i 个雕塑移动的最短距离,最后乘上系数即可。
先看代码:

#include 
#include 
using namespace std;

int main()
{
    int n,m;
    while (scanf("%d%d",&n,&m) == 2)
    {
        double ans = 0;
        for (int i= 1;i < n; i++)
        {
            double pos = (double)i / n * (n+m); //计算每个需要移动的雕塑的坐标
            ans += fabs(pos - floor(pos+0.5)) / (n+m); //累加移动距离
        }
        printf("%.4f\n",ans*10000);
    }
    return 0;
}

代码的确是很简洁,但我看了好久都没看懂大佬是如何实现的。。。于是动动手指头算了一算:
首先令 n=2,m=3 n = 2 , m = 3 ,当 i=1 i = 1 时,计算第一个雕塑距离为 12 1 2 ,我们知道最后的位置的分母一定是5,因此先通分:

12=525 1 2 = 5 2 5

可以看出,代码中的pos即为分母。
因此,我们要使得分母的 52 5 2 为整数,即找与 52 5 2 最近的整数即可,这就是代码中fabs(pos - floor(pos+0.5))的意义。

分析与证明

题并不困难,但仔细想想,还有两个问题没有解决。

1.为什么我们不考虑第一个( i=0 i = 0 )雕塑?

从直觉上讲,第一个雕塑的位置永远不会移动,事实上也的确如此。可以将圆想象成一个数轴,把第一个点放在圆点,左边的点放在负半轴,右边的点放在正半轴,可以简单证明,其中位数和平均数一定都为圆点。

2.有没有可能两个雕塑都要移动到同一个新位置?

可以简单证明:如果两个雕塑( m,n m , n )都要移动到同一个位置,因此,记该位置为 j j ,相邻两个位置为 j1 j − 1 j+1 j + 1 ,因此,雕塑 m m 和雕塑 n n 分别到 j1 j − 1 j+1 j + 1 的位置都小于新的间隔距离的一半,因此雕塑 m m 和雕塑 n n 的距离小于新的间隔距离,这与题意相违背,因此增加了雕塑后,两个雕塑的距离不可能大于原雕塑之间的距离。

你可能感兴趣的:(刷题)