• 【bzoj1604】【[Usaco2008 Open]Cow Neighborhoods】简单的谈谈曼哈顿距离


    这里写图片描述
    (最近p站上不去要死了)

    Description
    了解奶牛们的人都知道,奶牛喜欢成群结队.观察约翰的N(1≤N≤100000)只奶牛,你会发现她们已经结成了几个“群”.每只奶牛在吃草的时候有一个独一无二的位置坐标Xi,Yi(l≤Xi,Yi≤[1..10^9];Xi,Yi∈整数.当满足下列两个条件之一,两只奶牛i和j是属于同一个群的:
    1.两只奶牛的曼哈顿距离不超过C(1≤C≤10^9),即lXi - xil+IYi - Yil≤C.
    2.两只奶牛有共同的邻居.即,存在一只奶牛k,使i与k,j与k均同属一个群.
    给出奶牛们的位置,请计算草原上有多少个牛群,以及最大的牛群里有多少奶牛
    Input
    第1行输入N和C,之后N行每行输入一只奶牛的坐标.
    Output
    仅一行,先输出牛群数,再输出最大牛群里的牛数,用空格隔开.
    Sample Input
    4 2
    1 1
    3 3
    2 2
    10 10
    * Line 1: A single line with a two space-separated integers: the number of cow neighborhoods and the size of the largest cow neighborhood.
    Sample Output
    2 3
    OUTPUT DETAILS:
    There are 2 neighborhoods, one formed by the first three cows and the other being the last cow. The largest neighborhood therefore has size 3.

    这道题调死我了。。。

    其实主要是曼哈顿距离的运用。对于两个点(x1,y1)和(x2,y2),直接的曼哈顿距离是|x1-x2|+|y1+y2|。但这个绝对值太麻烦了,我们希望把它去掉。于是把点坐标转化一下:(A1,B1)和(A2,B2)(A1=x1+y1,B1=x1-y1,2同理)。于是曼哈顿距离就是max(A1-A2,B1-B2)。

    所以就把每个奶牛按新的横坐标排序。把她们挨个挨个扔进平衡树(set)里面(当然要保证平衡树里面的奶牛新横坐标之差都小于等于c),然后查找新纵坐标的前驱后继判断差值是否满足题意。如果小于等于c,就用并查集合并起来。

    #include<set>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N=100000+5;
    const int oo=0x3f3f3f3f;
    
    int n,c,fa[N],siz[N];
    bool vis[N];
    struct node{
        int x,y;
        int num;
    }a[N];
    set<node> S;
    
    inline bool operator < (const node &a,const node &b){
        if(a.y==b.y) return a.num<b.num;
        return a.y<b.y;
    }
    
    bool cp(const node &a,const node &b){
        return a.x==b.x&&a.y==b.y&&a.num==b.num;
    }
    bool cmp(const node &a,const node &b){
        return a.x<b.x;
    }
    int getfa(int x){
        if(fa[x]==x) return x;
        return fa[x]=getfa(fa[x]);
    }
    void merge(int x,int y){
        int fx=getfa(x),fy=getfa(y);
        if(fx==fy) return ;
        fa[fx]=fy;
    }
    int main(){
        scanf("%d%d",&n,&c);
        int xx,yy;
        for(int i=1;i<=n;i++){
            scanf("%d%d",&xx,&yy);
            a[i].x=xx+yy,a[i].y=xx-yy;
            a[i].num=i;
            fa[i]=i;
        }
        sort(a+1,a+n+1,cmp);
        node inf,_inf;
        inf.x=_inf.x=inf.num=_inf.num=0,inf.y=oo,_inf.y=-oo;
        S.insert(inf);
        S.insert(_inf);
        S.insert(a[1]);
        node pre,sub;
        int tmp=1;
        for(int i=2;i<=n;i++){
            while(a[i].x-a[tmp].x > c){
                S.erase(a[tmp]);
                tmp++;
            }
            S.insert(a[i]);
            pre=*--S.find(a[i]);
            sub=*++S.find(a[i]);
            if(pre.y!=-oo){
                if(a[i].y-pre.y<=c){
                    merge(a[i].num,pre.num);
                } 
            }
            if(sub.y!=oo){
                if(sub.y-a[i].y<=c){
                    merge(a[i].num,sub.num);
                } 
            }
        }
        int maxn=0,cnt=0;
        for(int i=1;i<=n;i++){
            int f=getfa(a[i].num);
            siz[f]++;
        }
        for(int i=1;i<=n;i++){
            if(siz[i]) cnt++;
            maxn=max(maxn,siz[i]);
        }
        printf("%d %d
    ",cnt,maxn);
        return 0;
    }
  • 相关阅读:
    优化你的手机游戏
    vuforia 结合 unity3d 开发 AR 的 androidAPP 总结
    self._raiseerror(v) File "D:GameDevelopmentPython27libxmletreeElementTree.py", line 1506, in _raiseerror
    自定义TexturePacker插件导出自己的plist文件
    还原TexturePacker plist 文件以及图片的方法 (切开各小图片)
    no module named firefly.master.master
    c#比较器 排序
    python ——面向对象进阶(反射,双下线方法,静态方法,类方法)
    python——模块和包 需要注意的地方
    举例详解Python中的split()函数的使用方法
  • 原文地址:https://www.cnblogs.com/LinnBlanc/p/7763118.html
Copyright © 2020-2023  润新知