• [BZOJ 3170][Tjoi 2013]松鼠聚会


    3170: [Tjoi 2013]松鼠聚会

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1346  Solved: 681
    [Submit][Status][Discuss]

    Description

    有N个小松鼠,它们的家用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点即上下左右四个点和对角的四个点,距离为1。现在N个松鼠要走到一个松鼠家去,求走过的最短距离。

    Input

    第一行给出数字N,表示有多少只小松鼠。0<=N<=10^5
    下面N行,每行给出x,y表示其家的坐标。
    -10^9<=x,y<=10^9

    Output

    表示为了聚会走的路程和最小为多少。

    Sample Input

    6
    -4 -1
    -1 -2
    2 -4
    0 2
    0 3
    5 -2

    Sample Output

    20

    题解

    我们可以发现, 我们走过一个对角线的距离也记为 $1$ , 这样的话我们可以直接补偿掉任意两个点间横坐标差与纵坐标差之间的差, 也就是说两点间的距离是这样的:

    [max(|x_0-x_1|,|y_0-y_1|)]

    实际上这是切比雪夫距离的定义, 但是单纯求所有其他点到某个点的切比雪夫距离和比较困难, 我们可以考虑按照一定规则转换点的坐标来使点与点间的曼哈顿距离等于原来的点之间的切比雪夫距离, 具体转换方式为 $(x,y) ightarrow (x+y,x-y)$ , 转化前两点的切比雪夫距离为转化后两点间的曼哈顿距离的一半. 正确性很容易证明.

    转化为曼哈顿距离后, 我们可以对所有横坐标排序并求前缀和, 然后对所有纵坐标排序求前缀和, 用前缀和减去目标的最终位置再求绝对值即可得到结果.

    参考代码

    GitHub

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <climits>
     4 #include <cstdlib>
     5 #include <iostream>
     6 #include <algorithm>
     7 
     8 const int MAXN=1e5+10;
     9 
    10 struct Point{
    11     long long x;
    12     long long y;
    13     long long posx;
    14     long long posy;
    15 };
    16 
    17 int n;
    18 long long sx[MAXN];
    19 long long sy[MAXN];
    20 
    21 Point P[MAXN];
    22 
    23 void Initialize();
    24 bool cmpx(const Point&,const Point&);
    25 bool cmpy(const Point&,const Point&);
    26 
    27 int main(){
    28     Initialize();
    29     std::sort(P+1,P+n+1,cmpx);
    30     for(int i=1;i<=n;i++){
    31         P[i].posx=i;
    32         sx[i]=sx[i-1]+P[i].x;
    33     }
    34     std::sort(P+1,P+n+1,cmpy);
    35     for(int i=1;i<=n;i++){
    36         P[i].posy=i;
    37         sy[i]=sy[i-1]+P[i].y;
    38     }
    39     long long ans=LLONG_MAX;
    40     for(int i=1;i<=n;i++){
    41         long long sum=0;
    42         sum+=P[i].x*(P[i].posx)-sx[P[i].posx];
    43         sum+=sx[n]-sx[P[i].posx]-(n-P[i].posx)*P[i].x;
    44         sum+=P[i].y*(P[i].posy)-sy[P[i].posy];
    45         sum+=sy[n]-sy[P[i].posy]-(n-P[i].posy)*P[i].y;
    46         // printf("%lld
    ",sum);
    47         ans=std::min(ans,sum);
    48     }
    49     printf("%lld
    ",ans/2);
    50     return 0;
    51 }
    52 
    53 void Initialize(){
    54     int x,y;
    55     scanf("%d",&n);
    56     for(int i=1;i<=n;i++){
    57         scanf("%d%d",&x,&y);
    58         P[i].x=x+y;
    59         P[i].y=x-y;
    60     }
    61 }
    62 
    63 inline bool cmpx(const Point& x,const Point& y){
    64     return x.x<y.x;
    65 }
    66 
    67 inline bool cmpy(const Point& x,const Point& y){
    68     return x.y<y.y;
    69 }
    Backup

     

  • 相关阅读:
    jQuery使用(十三):工具方法
    jQuery使用(十二):工具方法之type()之类型判断
    马化腾成中国新首富:一个多月身家增长77亿美元
    滴滴:设立1000万美元专项基金,援助海外司机骑手
    疫情查询
    自动获取时间html代码
    搜索引擎你还用百度吗?为什么?
    实现QQ内打开链接跳转至浏览器
    QQ靓号资料空白且空间开通教程
    斐波那契数列计算html代码
  • 原文地址:https://www.cnblogs.com/rvalue/p/7683974.html
Copyright © 2020-2023  润新知