• toj 4602 松鼠聚会


    题目:

    草原上住着一群小松鼠,每个小松鼠都有一个家。时间长了,大家觉得应该聚一聚。但是草原非常大,松鼠们都很头疼应该在谁家聚会才最合理。

    每个小松鼠的家可以用一个点x,y表示,两个点的距离定义为:点(x,y)和它周围的8个点(x-1,y),(x+1,y),(x,y-1),(x,y+1),(x-1,y+1),(x-1,y-1),(x+1,y+1), (x+1,y-1)距离为1。

    输入

    第一行是一个整数N,表示有多少只松鼠。接下来N行,第i行是两个整数x和y,表示松鼠i的家的坐标。(0≤N≤105,−109x,y≤109)

    输出

    一个整数,表示松鼠为了聚会走的路程和最小是多少。

    样例输入1

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

    样例输出1

    20

    样例输入2

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

    样例输出2

    15

    提示

    在第一个样例中,松鼠在第二只松鼠家(-1,-2)聚会;在第二个样例中,松鼠在第一只松鼠家(0,0)聚会

    题解:此题中定义的两点间距离,稍加分析就会发现是max(|xi-xj|, |yi-yj|);

    此时需要用到一个公式:

            max(|a|,|b|)=|(a+b)/2|+|(a-b)/2|;

    于是,两点间距离成了:

            |(xi-xj+yi-yj)/2|+|(xi-xj-yi+yj)/2|

          =   (|(xi+yi) - (xj+yj)| + |(xi-yi)-(xj-yj)|)/2

    公式中需要用xi+yi, xi-yi的值,这其实对应于点(xi,yi)在另一个坐标系中的坐标。我们对原来的点坐标做变换,令x'=x+y, y'=x-y,则上面的公式变成了:

            (|xi'-xj'| + |yi'-yj'|)/2

    分析到这儿就好做了,对于给定的点pi, 计算∑(|xi'-xj'| + |yi'-yj'|)/2还是很容易的,先整体做一遍预处理,按x排序计算一遍x坐标的前缀和,再按y排序,计算一次y坐标的前缀和就可以了。

    代码如下:

     1 #include <cstdio>
     2 #include <algorithm>
     3 #include <iostream>
     4 using namespace std;
     5 #define ll long long
     6 #define N 101000
     7 struct point {
     8     ll x, y;
     9     ll sx, sy;
    10     int cx, cy;
    11 }p[N];
    12 
    13 ll sumx, sumy;
    14 
    15 bool cmpx(point a, point b){
    16     return a.x < b.x;
    17 }
    18 
    19 bool cmpy(point a, point b){
    20     return a.y < b.y;
    21 }
    22 
    23 int main()
    24 {
    25     int n;
    26     while(~scanf("%d", &n))
    27     {
    28         sumx = sumy = 0;
    29         ll x, y;
    30         for(int i = 0; i < n; i++)
    31         {
    32             scanf("%lld %lld", &x, &y);
    33             p[i].x = x+y, p[i].y = x-y;
    34             sumx += p[i].x, sumy += p[i].y;
    35         }
    36         sort(p, p+n, cmpx);
    37         p[0].sx = p[0].cx = 0;
    38         for(int i = 1; i < n; i++)
    39         {
    40             p[i].sx = p[i-1].sx + p[i-1].x;
    41             p[i].cx = p[i-1].cx + 1;
    42         }
    43 
    44         sort(p, p+n, cmpy);
    45         p[0].sy = p[0].cy = 0;
    46         for(int i = 1; i < n; i++)
    47         {
    48             p[i].sy = p[i-1].sy + p[i-1].y;
    49             p[i].cy = p[i-1].cy + 1;
    50         }
    51         ll ans = -1;
    52         for(int i = 0; i < n; i++)
    53         {
    54             ll tm = p[i].cx*p[i].x - p[i].sx + (sumx-p[i].sx-p[i].x)-((n-p[i].cx-1)*p[i].x);
    55             tm += p[i].cy*p[i].y - p[i].sy + (sumy-p[i].sy-p[i].y)-((n-p[i].cy-1)*p[i].y);
    56             if(ans == -1 || tm < ans)ans = tm;
    57         }
    58         printf("%lld
    ", ans/2);
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    Leetcode: Rotate Image
    Leetcode: Longest Palindromic Substring && Summary: Palindrome
    Leetcode: Reverse Nodes in k-Group
    Leetcode: Substring with Concatenation of All Words
    Leetcode: Merge k Sorted List
    Summary: Java中函数参数的传递
    Leetcode: Generate Parentheses
    超级wifi
    路由器中继(repeater)模式 和 AP+WDS模式区别?
    route 的标志位
  • 原文地址:https://www.cnblogs.com/beisong/p/4457394.html
Copyright © 2020-2023  润新知