输入:当前墓碑规模n,添加规模m
解:取一个雕塑不动(在所有样例都成立),找到其他雕塑移动至距离最近的目标(保证不会有两个雕塑移动到同一目标点),此为最优解。
将圆按 10000:n+m 的比例缩小,借用取上下界得方法找到距离最近的目标节点。
#include <cstdio>
#include <cmath>
using namespace std;
int main(){
int n,m;
while(scanf("%d %d",&n,&m)==2){
double p,ans=0;
for(int i=1;i<n;i++){
p = (double)i*(n+m)/n;
ans += fabs(p-floor(p+0.5));
}
printf("%.4lf",ans*10000/(n+m));
}
return 0;
}
下面证明取一个雕塑不动是最优解得特性:
考虑规模为n和n+m的问题,我们将规模为n的点称作源点,规模为n+m的点称作目标点,设有一个源点与目标点重合(取一个墓碑不动),该点与圆心相连会将圆分割成对称的两部分,对应的源点和目标点都处于对称的位置,想象我们将所有源点顺时针或逆时针旋转至偏移x个单位,偏移量为x,我们需要证明偏移后的结果要比偏移前的结果更差。
若在偏移后有其他的源点与目标点重合,那么问题将会重复,所以我们只考虑偏移后不会再出现源点与目标点重合的结果,思考,偏移量最大是多少呢?
想象偏移后原先对称点的情况,它们刚好方向相反,偏移值相同,如果它们的目标点不变(目标点可能会发生变化),那么刚好抵消,不做考虑,最终偏移后的结果=0位置的偏移量+(目标点会变化的)点产生的偏移差。
目标点发生变化的情况,我们将其称之为越界点。
步骤(1):将问题分解成k个子问题;
在规模为n和n+m的问题中,可能会有若干个点与目标点重合(图1),我们取规模最小的问题,这些问题都是相同的,所以我们只考虑一个。
步骤(2):n可能为奇偶数;
实际上奇偶数得到的最终的结果是一样的,考虑时注意即可。
步骤(3):考虑最大偏移量;
考虑图2,要求不会在偏移后会有新的重合点,那么偏移量一定小于源点目标点的最小距离,没错,就是0位置左右的那两个点。再考虑下,什么时候源点目标点距离最远呢,那就是0位置对面的两(一)个点。这个结论叙述并不明确,但是在任意n和n+m规模下,这个结论总会成立,证明较简单,在此不做更细节的描述。
步骤(4):越界点是哪些,找到了越界点就可以计算总结果的差值。
先说明:从0位置开始,下一个源点与目标点的偏移量为a,再下一个为2a,接着ia。这是个要用到的结论(自行证明)。在图3中p1和p2是0位置对面的两个点,画竖线的两个点都是目标点的中点,这些都容易得到。接下来就是重点:p1’是p1关于中点对称点,p1p1’=a,p3是什么点,是上一个源点的复制,它右边长度是ia。假设源点旋转方向为逆时针,那么谁是越界点呢?在旋转偏移在a以内的情况下,只有p1会越界,p3都不会越界。也就是说在最小规模问题下,最多只可能有一个越界点。到此问题基本解决了。
整理一下,在最小规模问题下,设旋转偏移量为x,除了0位置和0对面的两(一+二)个点,其他的都不会产生影响。
差值=2ia-(x+(1-ia-x)+ia-x)=2ia-1+x。ia=1/2-1/2(a)。
差值=-a+x<0。所以旋转前的代价更小。
或者(n为偶数)差值=2ia-(2x+(1-ia-x)+ia-x)=-a<0。证毕。
图1
图2
图3
下面证明两个墓碑移动到同一目标点上:
反证法。假设两目标可以移动到同一目标点,两种情况,两源点在目标点同侧,或异侧。易发现两源点距离最大也要小于1。(.50000和.49999)但是源点规模小于目标点,所以源点间距大于目标点间距,可我们已经使目标点间距为1单位,所以源点间距一定大于1,发现矛盾。证毕。