0
点赞
收藏
分享

微信扫一扫

信息学奥赛一本通 1216:红与黑 | OpenJudge 2.5 1818:红与黑

在觉 2022-04-24 阅读 116
c++搜索

【题目链接】

ybt 1216:红与黑
OpenJudge 2.5 1818:红与黑

【题目考点】

1. 搜索 连通块问题

可以通过深搜或广搜解决
深搜时不做状态还原

【解题思路】

该题为连通块问题,可以用深搜或广搜来解决
统计@所在连通块的格子的数量。
vis数组,来标记某个位置是否已经访问过。
@所在位置出发开始进行搜索,每次搜索当前位置上下左右四个位置,如果该位置在地图内,没有访问过,而且是黑色的,那么就访问该位置,并从该位置开始进行搜索。每搜索到一个新的位置,统计搜索到的黑色瓷砖的位置数量。

【题解代码】

解法1:深搜

#include <bits/stdc++.h>
using namespace std;
#define N 25
char mp[N][N];//地图 
int w, h, dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}}, ans;//dir:方向数组 ans:黑色瓷砖数 
bool vis[N][N];//vis[i][j]:i,j位置是否已访问过 
void dfs(int sx, int sy)//深搜 搜索前访问 
{
	for(int i = 0; i < 4; ++i)//搜索(sx,sy)周围四个位置 
	{
		int x = sx + dir[i][0], y = sy + dir[i][1];
		if(x >= 1 && x <= h && y >= 1 && y <= w && vis[x][y] == false && mp[x][y] != '#')
		{//如果新位置(x,y)在地图内,没访问过,是黑色的 
			ans++;//黑色瓷砖计数增加 
			vis[x][y] = true;//访问(x,y) 
			dfs(x, y);
		}
	}
}
int main()
{
	int stx, sty;
    while(true)
    {
    	cin >> w >> h;
    	if(w == 0 && h == 0)
    		return 0;
    	for(int i = 1; i <= h; ++i)
    		for(int j = 1; j <= w; ++j)
    		{
    			cin >> mp[i][j];
    			if(mp[i][j] == '@')
    				stx = i, sty = j;//(stx,sty)记录起点位置 
    		}
    	memset(vis, 0, sizeof(vis));
    	ans = 1;//先访问,再深搜 
    	vis[stx][sty] = true;
		dfs(stx, sty);
    	cout << ans << endl;
	}
    return 0;
}

解法2:广搜

#include <bits/stdc++.h>
using namespace std;
#define N 25
struct Node
{
	int x, y;
	Node(){}
	Node(int a, int b):x(a),y(b){}
};
char mp[N][N];//地图 
int w, h, dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};//dir:方向数组 
bool vis[N][N];//vis[i][j]:i,j位置是否已访问过 
int bfs(int sx, int sy)//广搜,起点(sx, sy) 
{
	queue<Node> que;
	vis[sx][sy] = true;//访问起点并入队 
	que.push(Node(sx, sy));
	int ct = 1;//遍历到的黑色瓷砖的数量 
	while(que.empty() == false)
	{
		Node u = que.front();
		que.pop();
		for(int i = 0; i < 4; ++i)//访问u周围的位置 
		{
			int x = u.x + dir[i][0], y = u.y + dir[i][1];
			if(x >= 1 && x <= h && y >= 1 && y <= w && vis[x][y] == false && mp[x][y] != '#')
			{//如果新位置(x,y)在地图内,没访问过,是黑色的 
				vis[x][y] = true;//访问(x,y)位置 
				que.push(Node(x, y));
				ct++;//黑色瓷砖计数增加 
			}
		}
	}
	return ct;
}
int main()
{
	int stx, sty;
    while(true)
    {
    	cin >> w >> h;
    	if(w == 0 && h == 0)
    		return 0;
    	for(int i = 1; i <= h; ++i)
    		for(int j = 1; j <= w; ++j)
    		{
    			cin >> mp[i][j];
    			if(mp[i][j] == '@')//(stx,sty)记录起点位置 
    				stx = i, sty = j;
    		}
    	memset(vis, 0, sizeof(vis));//多组数据,记得清空变量 
    	cout << bfs(stx, sty) << endl;
	}
    return 0;
}
举报

相关推荐

0 条评论