http://acm.hdu.edu.cn/showproblem.php?pid=4311
大意:有(0<n<=100000)个点,找到一个点作为中间点,使得其他的点到它的曼哈顿距离和最短。
分析:不同的人有不同的思路,有人是找递推关系,有人是按x,y排序(我没完全看明白~~),来说说我的思路。直接来是2重大循环是会超时的,之前学习过模拟退火算法,里面有一个不断接近正确值的过程,即先近似再逐渐精确,受此启发,我来个简单粗暴的,计算出X的和,Y的和,分别除以n,得到一个平均值点(整型除法)
这样得到的点是近似平均的,所以接下来,我遍历所有的点把最接近它的前100个点装进一个数组,再一次来个二重循环,不过这次二重循环的第一层循环的长度由1e5变成了1e2,哈哈哈。。。
大意:有(0<n<=100000)个点,找到一个点作为中间点,使得其他的点到它的曼哈顿距离和最短。
分析:不同的人有不同的思路,有人是找递推关系,有人是按x,y排序(我没完全看明白~~),来说说我的思路。直接来是2重大循环是会超时的,之前学习过模拟退火算法,里面有一个不断接近正确值的过程,即先近似再逐渐精确,受此启发,我来个简单粗暴的,计算出X的和,Y的和,分别除以n,得到一个平均值点(整型除法)
这样得到的点是近似平均的,所以接下来,我遍历所有的点把最接近它的前100个点装进一个数组,再一次来个二重循环,不过这次二重循环的第一层循环的长度由1e5变成了1e2,哈哈哈。。。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <stack>
#include <algorithm>
using namespace std;
const int N=1e5+10;
typedef long long LL;
struct point{
LL x,y;
}p[N];
struct node{
LL dis,order;
}ds[N];
LL manha(point a,point b){
return abs(a.x-b.x)+abs(a.y-b.y);
}
int cmp(node t1,node t2){
return t1.dis<t2.dis;
}
int main()
{
//freopen("cin.txt","r",stdin);
LL t,n;
cin>>t;
while(t--){
scanf("%lld",&n);
LL sx=0LL,sy=0LL;
for(int i=0;i<n;i++) {
scanf("%lld%lld",&p[i].x,&p[i].y);
sx=sx+p[i].x;
sy=sy+p[i].y;
}
sx=sx/n;
sy=sy/n;
LL dis=1LL<<60;
point center;
for(int i=0;i<n;i++){
LL d=abs(p[i].x-sx)+abs(p[i].y-sy);
if(d<dis){
dis=d;
center.x=p[i].x;
center.y=p[i].y;
}
}
for(int i=0;i<n;i++){
ds[i].dis=manha(center,p[i]);
ds[i].order=i;
}
sort(ds,ds+n,cmp);
LL ans=1LL<<60;
for(int i=0;i<100;i++){
int dex=ds[i].order;
LL sum=0;
for(int j=0;j<n;j++){
sum=sum+manha(p[dex],p[j]);
}
ans=min(ans,sum);
}
printf("%lld\n",ans);
}
return 0;
}