zoukankan      html  css  js  c++  java
  • bzoj 3170: [Tjoi 2013]松鼠聚会

    转载请注明出处:

    http://www.cnblogs.com/hzoi-wangxh/p/7738617.html

    3170: [Tjoi 2013]松鼠聚会
    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
    HINT

    Source

    题解:
    设一只松鼠坐标为(x1,y1),另一只坐标为(x2,y2),则其中一只到另一只的距离是max(|x1-x2|,|y1-y2|)。
    这其实是切比雪夫距离,但是直接用它不好做,我们可以将其转化为曼哈顿距离。
    转化如下:
    如果|x1-x2|>|y1-y2|,dis=|x1-x2|,否则dis=|y1-y2|。
    我们可以将其转化为dis=|(x1-x2)/2+(y1-y2)/2|+|(x1-x2)/2-(y1-y2)/2|。
    与上面的式子是等价的。
    dis=1/2*(|(x1+y1)-(x2+y2)|+|(x1-y1)-(x2-y2)|)
    因此,我们只需要对每一个坐标,记录a=(x+y),b=(x-y),求其差的前缀和即可。
    附上代码:

    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define int long long
    #define mmin(a,b) (a<b?a:b)
    struct tree{
        int xx,yy,id;
    }q[101000];
    int prex[100100],nxtx[1001000],prey[100100],nxty[100100],n,ans=10000000000000000ll;
    bool cmp1(const tree s1,const tree s2)
    {
        return s1.xx<s2.xx;
    }
    bool cmp2(const tree s1,const tree s2)
    {
        return s1.yy<s2.yy;
    }
    signed main()
    {
    //  freopen("in.txt","r",stdin);
        scanf("%lld",&n);
        for(int i=1;i<=n;i++)
        {
            int x,y;
            scanf("%lld%lld",&x,&y);
            q[i].xx=x+y;
            q[i].yy=x-y;
            q[i].id=i;
        }
        sort(q+1,q+n+1,cmp1);
        for(int i=1;i<=n;i++) prex[q[i].id]=prex[q[i-1].id]+(q[i].xx-q[i-1].xx)*(i-1);
        for(int i=n;i>=1;i--) nxtx[q[i].id]=nxtx[q[i+1].id]+(q[i+1].xx-q[i].xx)*(n-i);
        sort(q+1,q+n+1,cmp2);
        for(int i=1;i<=n;i++) prey[q[i].id]=prey[q[i-1].id]+(q[i].yy-q[i-1].yy)*(i-1);
        for(int i=n;i>=1;i--) nxty[q[i].id]=nxty[q[i+1].id]+(q[i+1].yy-q[i].yy)*(n-i);
        for(int i=1;i<=n;i++)
            ans=mmin(ans,prex[i]+nxtx[i]+prey[i]+nxty[i]);
        ans/=2;
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    vscode 整理————开篇之力(一)
    重学c#系列——datetime 和 datetimeoffset[二十一]
    重新点亮shell————什么是shell[一]
    重新整理 .net core 实践篇——— 权限中间件源码阅读[四十六]
    为什么构建容器需要Namespace?
    基于Windows Mobile 5.0的掌上天气预报设计
    使用.NE平台调用服务访问非托管 DLL 中的函数
    .NET Framework 3.0 RC1 开发环境构建
    ASP.NET未处理异常的处理
    基于Silverlight的Windows Phone 推箱子程序开发
  • 原文地址:https://www.cnblogs.com/hzoi-wangxh/p/7738617.html
Copyright © 2011-2022 走看看