hdu - 4312 - Meeting point-2 - 数学 + 想法

题意, 一个方格到相邻八个点的距离都为1.

给你好多个点的坐标,让你求一个点满足到其他点的距离最短。

解:

   其实也是暴力枚举,貌似没有比他更好的方法。 但是枚举的时候做些预处理就行,参见4311.

   其他就需要了解的就是chebyshev距离和manhattan距离的转化了。

   我照着题解静下心来认真看了,终于觉得题解是对的了。


平面上两点间的 Chebyshev距离为 max(|x1-x2|, |y1-y2|)

                      

           Chebyshev                                                Manhattan

对于原坐标系中两点间的 Chebyshev 距离,是将坐标轴顺时针旋转45度并将所有点的坐标值放大sqrt(2)倍所得到的新坐标系中的Manhattan距离的二分之一。

大家可以画图想一下……

假设有两点(x1,y1), (x2,y2),不妨设 x1>x2(否则交换这两点即可)。

则Chebyshev距离 D1 = max(|x1-x2|, |y1-y2|)

这两点个对应到新坐标系中的坐标为 (x1-y1, x1+y1), (x2-y2, x2+y2)

则Manhattan 距离D2 = |x1-y1-x2+y2| + |x1+y1-x2-y2|



分四种情况讨论:

1.1 y1>y2 && x1-x2>y1-y2

D1 = max(x1-x2, y1-y2) = x1 - x2

D2 = x1-y1-x2+y2 + x1+y1-x2-y2 = 2(x1-x2)

1.2 y1>y2 && x1-x2<=y1-y2

D1 = max(x1-x2,y1-y2) = y1-y2

D2 = -(x1-y1-x2+y2) + x1+y1-x2-y2 = 2(y1-y2)

2.1 y1<=y2 && x1-x2>y2-y1

D1 = max(x1-x2, y2-y1) = x1-x2

D2 = x1-y1-x2+y2 + x1+y1-x2-y2 = 2(x1-x2)

2.2 y1<=y2 && x1-x2<=y2-y1

D1 = max(x1-x2, y2-y1) = y2-y1

D2 = x1-y1-x2+y2 - (x1+y1-x2-y2) = 2(y2-y1)



所以先将Chebyshev距离形式转化成Manhattan距离的形式再求解,求解过程参考 Meeting point-2


将4311代码改了三行,就过了。。。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#define maxn 100010
typedef long long L;
using namespace std;

struct Node{
    long long x,y;
    int id;
} p[maxn];
long long sumx[maxn],sumy[maxn];
bool cmpx(Node a , Node b){
    return a.x < b.x;
}
bool cmpy(Node a, Node b){
    return a.y < b.y;
}
int T, n;
long long tmpx, tmpy;//改的地方
int main(){
    scanf("%d",&T);
    while(T --){
        scanf("%d",&n);
        for(int i = 1; i <= n; ++ i){
            scanf("%I64d%I64d", &tmpx, &tmpy);
            p[i].x = tmpx - tmpy;//改的地方
            p[i].y = tmpx + tmpy;//改的地方
        }
        sort(p + 1, p + 1 + n, cmpx);
        sumx[1] = p[1].x;p[1].id = 1;

        for(int i = 2; i <= n; ++ i){
            sumx[i] = sumx[i - 1] + p[i].x;
            p[i].id = i;
        }

        sort(p + 1, p + 1 + n, cmpy);
        sumy[1] = p[1].y;
        for(int i = 2; i <= n; ++ i){
            sumy[i] = sumy[i - 1] + p[i].y;
        }

        long long ans = (1LL << 60);//
        for(int i = 1; i <= n; i ++){
            int j = p[i].id;

            long long yy = ( p[i].y ) * (i * 1.0) - sumy[i];
            yy += (sumy[n] - sumy[i] - (p[i].y) * ((n - i) * 1.0) );

            long long xx = ( p[i].x ) * (j * 1.0) - sumx[j];
            xx += (sumx[n] - sumx[j] - (p[i].x) * ((n - j) * 1.0) );
            xx += yy;

            ans = min(xx,ans);
        }
        printf("%I64d\n", ans / 2);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值