hiho 1487 并查集+搜索 [Offer收割]编程练习赛11 problem C 岛屿3

来源:互联网 发布:全网通手机淘宝 编辑:程序博客网 时间:2024/05/21 14:03

#1487 : 岛屿3

时间限制:10000ms
单点时限:1000ms
内存限制:256MB

描述

H国正在进行一项持续N周的填海造岛工程。整片工程海域可以被看作是1000x1000的网格。

每周都有一块1x1的单位方格海域被填成陆地。如果我们将连成一片的陆地(一块单位方格与它上下左右4个单位方格是相连的)视为岛屿,H国想监测每周末整片海域中一共存在有多少个岛屿,以及这些岛屿的总面积和总周长各是多少。

假设工程持续三周,第一周被填的海域坐标是(0, 0),那么第一周结束后有1座岛屿、总面积是1、总周长是4:

#........

第二周被填的海域坐标是(1, 1),那么第二周结束后有2座岛屿、总面积是2、总周长是8:

#...#....

第三周被填的海域坐标是(1, 0),那么第三周结束后有1座岛屿、总面积是3、总周长是8:

#..##....

你能完成这项任务么?

输入

第一行包含一个整数N,表示工程持续的周数。(1 <= N <= 100000)  

以下N行每行包含两个整数x和y,表示当周被填的海域坐标。(0 <= x, y < 1000)

输出

输出N行,每行包含3个整数,依次是当周末岛屿的数量、总面积和总周长。

样例输入
3  0 0   1 1   1 0
样例输出
1 1 4  2 2 8  1 3 8 


题意非常简单,1000*1000的矩阵,一开始是空的,每次不重复的放一个点,求4向联通集的个数,总面积和总周长。

这里联通集我们用并查集处理一下,二维的点集,可以把x,y映射到1000x+y上构成一维的。因为xy范围都在1000内,用并查集以便于统计联通集的个数,每次放入一个新块之后,把周边的相邻的点都先存到一个vector里,然后挨着判断一下是不是一个集合,如果不是一个集合,那么联通集总数就要-1,如果不相邻,总数就+1,新增周长可以用4-2*相邻的边数来计算。


这个题调试了半天,2.30比赛结束,我2.31提交上去1A了,T_T。问题出在我这一堆for循环上,有一个地方手抖敲错了。。。for(int k=0;k<4;i++),我调了将近半个小时,就是没看出来哪里不对,程序运行到这就卡住了,比赛结束的一瞬间我把i改成k交上去就A了。天命如此……自己太水,不想说什么了,这又让我想起来几次区域赛打铁的经历,跟这次大同小异,有毒呀。





#include <iostream>#include <stdio.h>#include <math.h>#include <stdlib.h>#include <string>#include <string.h>#include <algorithm>#include <vector>#include <queue>#include <set>#include <map>#include <stack>using namespace std;//x*1000+y;int par[1000005];int tall[1000005];void init(int n){    for(int i=1;i<=n;i++){        par[i]=i;        tall[i]=0;    }}int find_root(int x){    if(par[x]==x){        return x;    }    else{        return par[x]=find_root(par[x]);    }}void unite(int x,int y){    x=find_root(x);    y=find_root(y);    if(x==y)return;    if(tall[x]<tall[y]){        par[x]=y;    }    else{        par[y]=x;        if(tall[x]==tall[y])tall[x]++;    }}bool same(int x,int y){    return find_root(x)==find_root(y);}int F[1005][1005];int d[4][2]={1,0,0,1,0,-1,-1,0};int n;bool cango(int x,int y){    return x>=0&&x<1000&&y>=0&&y<1000;}int main(){    while(cin>>n){        memset(F,0,sizeof(F));        init(1000009);        int num=0;//数量        int S=0;//面积        int L=0;//周长        for(int i=0;i<n;i++){            int x,y;            scanf("%d%d",&x,&y);            F[x][y]=1;            int V=x*1000+y+1;            int find_a_new=1;//四周都是空的            int chongbian=0;//重合边数量            vector<int>P;//所有边界点            P.clear();            for(int k=0;k<4;k++){                int nx=x+d[k][0];                int ny=y+d[k][1];                if(cango(nx,ny)){                    int nV=nx*1000+ny+1;                    if(F[nx][ny]==1){                        P.push_back(nV);                        chongbian++;                        find_a_new=0;//没找到新的                        if(same(nV,V)){                            //chongbian++;                            //unite(nV,V);                        }                        else{                            //unite(nV,V);                            //chongbian++;                        }                    }                    else{                    }                }                else{                }               // cout<<"fuck"<<endl;            }            if(find_a_new==1){                num++;                L+=4;            }            else{                unite(P[0],V);               // cout<<"stat "<<P.size()<<endl;                //cout<<P[0]<<" !!! "<<P[1]<<endl;                for(int j=1;j<P.size();j++){                    if(!same(P[j],P[j-1])){                        num--;                        unite(P[j],P[j-1]);                    }                }               // cout<<"stat2"<<endl;                L+=4-2*chongbian;            }            S++;            cout<<num<<" "<<S<<" "<<L<<endl;        }    }    return 0;}





1 0
原创粉丝点击