国家宝藏

Description

话说ZY日行一善,终于天可怜见,某日他居然进入了传说中的国家宝藏。这个区域是个N*N
的矩形方块。每个方块可能放置的是宝物或者是不可翻越的障碍。当某个方块放的是宝物时
,如果其上下左右的某个方块放置的亦是宝物时,则两个方块则被认为是互相连通的。ZY想
到所有的宝物都拾走,但单凭他一个人的力量是不行的,此时地也怜见了,从地下冒出这个
矩形方块的地形图,ZY有了这张地图就可以Judge出整个矩形方块被分成了多少个连通块,
哈哈,此时他拿出他心爱的G11,召唤Oi队员来帮他的忙,但到底要叫多少个人来呢?(我
们假设一个人可以占据一个连通块)于是这个光荣的任务就交给你了,ZY和他的Oi队员们今
后能否过上幸福的生活就全看你的了……

Input

第一行一个数字N,代表矩形方块的长,N<=1000
接下来的N行N列,代表宝物的分布,其中0代表宝物,1代表障碍。

Output

请输出有多少个连通块。

Sample Input

【输入样例1】
3
0 0 0
1 1 1
0 0 0
【输入样例2】
3
0 1 1
0 0 0
1 1 0

Sample Output

【输出样例1】
2
【输出样例2】
1

sol:此题粗看很简单,用bfs或dfs搜索就好了,但注意此题的内存限制是3M,因此无法存储整张图,从而无法进行遍历点的操作了。
但我们还是可以存储2行图的,于是可以对当前点[i,j]进行分类讨论。若当前点是宝藏,则看与上方和左边点是否连通,有以下几种情况:
1.上方点和左边点都不是宝藏,则当前点独立成一个连通块,连通块数量增加一个;
2.上方点不是宝藏,左边点是宝藏,则当前点与左边点构成一个连通块;
3.上方点是宝藏,左边点不是宝藏,则当前点与上方点构成一个连通块;
4.上方点和左边点都是宝藏,则通过当前点进行连通,这时要看上方点和左边点是否属同一个连通块,如果不是,则连通后连通块数量减少一个。
当然,如果当前点不是宝藏,就不用管它了。
此题可用并查集实现。
另外该题的数据,如果出现极端情况,如点是01相间给出,则该方法仍不能实现。
 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 int k,t,p,q,n,tot,ans;
 5 int father[50010];
 6 bool mapp[2][50010];
 7 int f[2][50010];
 8 int find(int x)
 9 {
10     if(x!=father[x])
11         father[x]=find(father[x]);
12     return father[x];
13 }
14 int main()
15 {
16     scanf("%d",&n);
17     for(int i=1;i<=50000;i++)
18         father[i]=i;
//特别要注意,这里的father[i]是指编号为i的连通块的父亲是谁,后面判断两个连通块是否同一个连通块的时候,就根据father[i]来判断。
19 t=0; 20 for(int i=1;i<=n;i++)//处理n行矩形方块 21 { 22 t^=1; 23 for(int j=1;j<=n;j++)//读入每行的j列方块信息 24 { 25 scanf("%d",&k); 26 if(k==0) 27 mapp[t][j]=true; 28 else 29 mapp[t][j]=false; 30 } 31 for(int j=1;j<=n;j++) 32 { 33 if(mapp[t][j])//如果当前方块是宝藏 34 { 35 if(!mapp[t^1][j]&&!mapp[t][j-1])//其上方和左边方块不是宝藏 36 { 37 tot++;//连通块的编号 38 ans++;//连通块数量 39 f[t][j]=tot;//当前t行j列单独成为一个连通块 40 } 41 else 42 if(!mapp[t^1][j]&&mapp[t][j-1])//上方不是宝藏,左边是 43 f[t][j]=f[t][j-1];//当前方块与左边成为一个连通块 44 else 45 if(mapp[t^1][j]&&!mapp[t][j-1])//上方是宝藏,左边不是 46 f[t][j]=f[t^1][j];//当前方块与上方成为一个连通块 47 else//左边和上方都是宝藏,则通过当前方块连通 48 { 49 f[t][j]=f[t^1][j]; 50 p=find(f[t^1][j]); 51 q=find(f[t][j-1]); 52 if(p!=q)//看上方方块和左边方块是否是同一个连通块,若不是 53 { 54 father[p]=min(p,q);//连通 55 father[q]=min(p,q); 56 ans--;//连通块数量-1 57 } 58 } 59 } 60 } 61 } 62 printf("%d",ans); 63 }


 
原文地址:https://www.cnblogs.com/cutepota/p/12462903.html