HDU 4311 Meeting point-1

来源:互联网 发布:纹理映射算法 编辑:程序博客网 时间:2024/04/25 03:16

HDU 4311 : Meeting point-1 http://acm.hdu.edu.cn/showproblem.php?pid=4311  

题目大意:给出若干个点,找到一个点,使得所有的点到这个点的曼哈顿距离之和最小,求这个最小的距离即可。

题目误区:找到的这个点,一定要是给定点中的一个,不是给定点中的,虽然能使曼哈顿距离之和最小,但也不满足题意,不可取。所以我们不能只看x,求得其他点距离任意一个点最小的距离。然后再去看y,这样有可能找到的不是最小的距离。

题目分析:由于点的个数比较多,而且坐标的范围也比较大,直接去找肯定会超时,所以,我们采用把x和y暂时分开来找的方法。也算是横向遍历每一个所给出的点,复杂度也就是O(n)。对于x,我们要先对x进行从小到大排序,然后把从x1到xn与x0之间的距离更新在结构体数组中,即结构体数组首位为0,由于我们要求的是最小的距离,所以把累加的距离也放在一个sumx的数组中,并把这样的顺序记录下来。然后同理对y进行同样的操作,之后把其他点到x0点的距离记录下来了。

而对于任意的xi,我们可以在其他点与x0的距离的基础上进行增减,画图解释一下:




代码实现如下:

#include <iostream>#include <stdio.h>#include <algorithm>using namespace std;const int MAXN=100005;struct node{    long long x,y,id; //由于有两次排序,id用来记录第一次排完序之后的顺序}point[MAXN];long long sumx[MAXN],sumy[MAXN]; //分别用来存放从|x1x0|到|xnx0|的距离之和,和从|y1y0|到|yny0|的距离之和bool cmpx(node a,node b) //按x递增给结构体排序{    if(a.x!=b.x)        return a.x<b.x;    return a.y<b.y;}bool cmpy(node a,node b) //按y递增给结构体排序{    if(a.y!=b.y)        return a.y<b.y;    return a.x<b.x;}int main(){    int t,n;    long long sum;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        for(int i=0; i<n; i++)        {            scanf("%lld%lld",&point[i].x,&point[i].y);        }        sort(point,point+n,cmpy);        sumy[0]=0;        point[0].id=0;        for(int i=1; i<n; i++)        {            point[i].y=point[i].y-point[0].y;            sumy[i]=sumy[i-1]+point[i].y;            point[i].id=i;        }        point[0].y=0;        sort(point,point+n,cmpx);        sumx[0]=0;        for(int i=1; i<n; i++)        {            point[i].x=point[i].x-point[0].x;            sumx[i]=sumx[i-1]+point[i].x;        }        point[0].x=0;        sum=sumx[n-1]+sumy[n-1];        for(int i=1; i<n; i++)        {            long long ans= i * point[i].x - sumx[i-1] + sumx[n-1] - sumx[i] - (n - i - 1) * point[i].x;            ans+=(point[i].id*point[i].y-sumy[point[i].id-1]+sumy[n-1]-sumy[point[i].id]-(n-point[i].id-1)*point[i].y);            if(ans<sum)            {                sum=ans;            }        }        printf("%lld\n",sum);    }    return 0;}



1 0
原创粉丝点击