队列之连通块

队列之连通块

[问题描述]
一个nm的方格图,一些格子被涂成了黑色,在方格图中被标为1,白色格子标为0.问有多少个四连通的黑色格子连通块。 四连通的黑色格子连通块指的是一片由黑色格子组成区域,其中的每个黑色格子能通过四连通的走法(上下左右),只走黑色格子,到达该联通块中的其它黑色格子。
[输入]
第一行两个整数n,m(1<=n,m<=100),表示一个nm的方格图.
接下来n行,每行m个整数,分别为0或1,表示这个格子是黑色还是白色。
[输出]
只有一行,一个整数ans,表示图中有ans个黑色格子连通块.*
样例输入:3 3
1 1 1
0 1 0
1 0 1
样例输出:3

思路:
1.搜索出第一个黑色格子入队。
2.然后用其拓展出其相邻的黑色格子。
3.将这个搜索过的黑格子出队。
4…所拓展出的新格子重复2,3。
5.直到相邻的都是白格子,从1开始。

特殊做法用数组代替队列
原因队列没有二维的,且队列只有两个口,出入队不方便**

定义变量

int a[110][110];//a数组存储所输入的黑格子,这里定义为全局方便直接函数调用 
int q[110][110];//q数组用来充当队列
int n,m;//输入的行和列
int flag[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//相邻的四个黑格子
bool p[110][110];//p数组用来判断这个黑格子是否被搜索过 

bfs函数,搜索,出入队

void  bfs(int x,int y)
{
    int front=0,rear=2;
    q[1][0]=x;//将新搜索到的点保存到q数组 
    q[1][1]=y;
    while(front<rear-1)//front为队头,rear为队尾 
    {
        front++;//充当出队操作
        x=q[front][0];
        y=q[front][1];
        for(int i=0;i<4;i++)
        {
            int x1=x+flag[i][0];//(x1,y1)就是(x,y)的相邻的点 
            int y1=y+flag[i][1];
            if(x1<1 || x1>n || y1>m || y1<1 || !a[x1][y1] || p[x1][y1])
            {
                continue;
            }
            p[x1][y1]=true;
            q[rear][0]=x1;//如果这是一个未被搜索到的黑格子,那么就将其入队 
            q[rear++][1]=y1;//找到后队尾向后延伸,让新点入队 

        }
	}
}

主函数(main)

int main()
{
	int ans=0; 
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(a[i][j] && !p[i][j])
			{
				++ans;
				bfs(i,j);
			}
		}
		
	}
	cout<<ans;
	return 0;
}

做完以上之后
我们想一下优化方案

优化方案:
想法:将p数组去掉
思路:既然a数组中1表示这是一个黑格子 ,且q数组已经把这个黑格子保存了,
那么我们可以将已搜索过的黑格子变为0(白格子)
做法

	1.主函数中的判断循环的判断条件改为
				if(a[i][j])
				{
					++ans;
					bfs(i,j);
				} 
	2.函数bfs中的for循环的判断条件改为 
			if(x1<1 || x1>n || y1>m || y1<1 || !a[x1][y1])
	        {
	              continue;
	        }
    3.bfs中不符合条件的内容改为 
			a[x1][y1]=0;
	        q[rear][0]=x1;
	        q[rear++][1]=y1;

这样就不需要p数组了

发布了6 篇原创文章 · 获赞 9 · 访问量 2705
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览