hdu 4311 Meeting point-1 (快速求解曼哈顿距离和)

http://acm.hdu.edu.cn/showproblem.php?pid=4311
大意:有(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;
}




你可能感兴趣的:(数学)