要建立一个信号基站服务n个村庄,这n个村庄用平面上的n个点表示。假设基站建立的位置在(X,Y),则它对某个村庄(x,y)的距离为max{|X – x|, |Y – y|}, 其中| |表示绝对值,我们的目标是让所有村庄到信号基站的距离和最小。 基站可以建立在任何实数坐标位置上,也可以与某村庄重合。 输入: 给定每个村庄的位置x[],y[],x,y都是整数,满足:-1000000000 < x,y < 1000000000 村庄个数大于1,小于101。
输出: 所有村庄到信号基站的距离和的最小值。 关于精度: 因为输出是double。我们这样判断对错,如果标准答案是A,你的答案是a,如果|A – a| < 1e-3 我们认为是正确的,否则认为是错误的。(题目|A – a| < 1e-3具体成这样,误导..)
样例:
假设有4个村庄位置分别为 (1,4) (2,3) (0,1) (1,1) 我们的结果是5。因为我们可以选择(1.5,2.5)来建立信号基站。 bestDistance = max(|1.5-1|, |2.5-4|) + max(|1.5-2|,|2.5-3|) + max(|1.5-0|,|2.5-1|) + max(|1.5-1|,|2.5-1|) = max(0.5, 1.5) + max(0.5,0.5) + max(1.5,1.5) + max(0.5,1.5) = 1.5 + 0.5 + 1.5 + 1.5 = 5
首先这题目就把我吓到了,有点恐惧比较大的数,感觉容易超时,而且这一题让我感觉像个刺猬,不知道由何入手,因为涉及到double,连穷举我都无法做到,不过等做出来后,才发现自己被坑了,double型数据,double型的基站,都是用来迷惑的。
首先是对max进行剖析
假设基点坐标是(X,Y),村庄坐标分别是(x1,y1),(x2,y2)...(xn,yn)
max{|X-x1|,|Y-y1|},等价于(|X+Y-(x1+y1)| + |X-Y-(x1-y1)|)/2;//这个是一切分析的基础
所以基站与各点的距离和:
bestDistance = (|X+Y-(x1+y1)| + |X-Y-(x1-y1)| + |X+Y-(x2+y2)| + |X-Y-(x2-y2)| +……+ |X+Y-(xn+yn)|+|X-Y-( xn-yn)|)/ 2;
其中,x1+y1 、x1-y1 、 x2+y2 、 x2-y2 、……、xn+yn 、 xn-yn 由题可知;
U[i] = xi + yi , V[i] = xi - yi ;(i由1~n),i = 0表示基站
所以bestDistance = (|U0- U1| + |V0- V1| + | U0- U2| + |V0- V2| +……+ | U0 - Un| + |V0- Vn|) / 2;
= (|U0 - U1|+ |U0 - U2| + ……+ |U0 - Un|) +(|V0 - V1| + |V0 - V2| +…… + |V0 - Vn|) / 2;
看到(|U0 - U1|+ |U0 - U2| + ……+ |U0 - Un|) 大家可能就比较熟悉了,假设U1-Un是数轴上的点,求和即是在数轴上的一个点到这些点的距离之和;
所以bestDistance也就此产生。
代码看上去简单多了:
#include <iostream>
#include <algorithm>
using namespace std;
#ifdef WIN32
typedef __int64 ll;
#else
typedef long long ll;
#endif
__int64 MinDistance(__int64 dis[], __int64 n)
{
sort(dis, dis + n); //排序之后即可直接头尾相减即可
__int64 left = 0; //左
__int64 right = n - 1; //右
__int64 sum = 0;
while (right >= left) //类似计算数轴上的点,距离各个点之和最小
{
sum += dis[right--] - dis[left++];
}
return sum;
}
double bestDistance(int n, const int *x,const int *y) {
__int64 U[100], V[100];
for (__int64 i = 0; i < n; ++ i)
{
U[i] = x[i] + y[i];
V[i] = x[i] - y[i];
}
return (MinDistance(U, n) + MinDistance(V, n)) / 2.0;
}
//start 提示:自动阅卷起始唯一标识,请勿删除或增加。
int main()
{
int n = 4;
int x[] = {1, 2, 0 ,1};
int y[] = {4, 3, 1, 1};
cout<<bestDistance(n, x, y);
return 0;
}
//end //提示:自动阅卷结束唯一标识,请勿删除或增加。
其中
#ifdef WIN32
typedef __int64 ll;
#else
typedef long long ll;
#endif
是因为测试点的数值比较大,int无法招架;
在sum += dis[right--] - dis[left++]中,若是偶数个点,选择第n/2-1与n/2即可,奇数则必须在n/2点;
真正的基站并没有建立,只求最佳距离,当然,点也不是唯一的。
工程相关:http://blog.csdn.net/xjm199/article/details/17474059
不足之处,还望大神们提点...多多交流.......o(∩_∩)o