hdu 4311 Meeting point-1

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
题意:给你n个点问在其中任选一点到其他点的距离和最小是多少。
分析:|p1p2| = |x1 – x2| + |y1 – y2|;
看数据范围是不能暴力的。我们分开求,先求x方向的的最距离,然后在加上y方向上距离。
先把点按x排序,设排序后为X0,X1,X2,…,Xn-1。然后求每个点到x0的距离和sumx;
关键点在下面:我们在求每个点到x1的距离时,sumx加上X1左边的(1-1)个|X1X0|,减去X2右边的(n-1 – 1 -1)个|X1X0|,求得新的sumx。也就说在求每个点到xi的距离时,sumx加上Xi左边的(i-1)个|XiXi-1|,减去X2右边的(n-1 – i -1)个|X1X0|,求得新的sumx。
同理可得y,加到对应的点上即可。
*/
#include <iostream>
#include <algorithm>
using namespace std;
#define ll __int64
const int maxn = 100005;
struct node
{
    ll x, y,id;
}point[maxn];
ll sumy[maxn], sumx[maxn];

bool cmpx(node a, node b)
{
    if(a.x != b.x)
    return a.x < b.x;
    return a.y < b.y;
}

bool cmpy(node a, node b)
{
    if(a.y != b.y)
    return a.y < b.y;
    return a.x < b.x;
}

int main()
{
    int t, n;
    ll ans;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(int i = 0; i < n; i++)
        {
            scanf("%I64d %I64d", &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[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[0].x;
            sumx[i] = sumx[i-1] + point[i].x;
        }
        point[0].x = 0;
        ans = sumy[n-1] + sumx[n-1];
        for(int i = 1; i < n; i++)
        {
            ll sum = i * point[i].x - sumx[i-1]+ sumx[n-1] - sumx[i] - (n - i - 1) * point[i].x;
            sum += ( point[i].id*point[i].y - sumy[point[i].id-1] + sumy[n-1] - sumy[point[i].id] - (n -1 - point[i].id)* point[i].y );
            if(sum < ans) ans = sum;
        }
        printf("%I64d\n", ans);

    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值