迷宫题模板训练

这几天做了些迷宫题,感觉都是一个套路,题目不难但是细节需要注意,可以小小总结一下
在这里插入图片描述
问题 A: 扫雷布盘
题目描述
相信大家一定玩过扫雷游戏。可是扫雷游戏怎么做的呢?

小QQ是个聪明好学的好孩子,他决定编一个扫雷小游戏。

他第一步要做的就是布置雷盘,在一个n*n的棋盘上埋下若干个雷点,埋下地雷的位置用数字‘9’表示,没有地雷的位置用数字0表示。

但是刚埋完雷,小QQ的好朋友小RED来了,他就和小RED玩去了。小QQ在临走前交代你把地雷布盘的任务完成。

你只要把地雷周围的‘0’修改成该位置附近的地雷个数就行啦。(附近指上、下、左、右、左上、左下、右上、右下八个位置)

输入
输入一个正整数n,(0<n<100),然后输入一个n*n的雷盘。雷盘上只有两种字符:‘0’和‘9’,‘0’表示安全区域,‘9’表示埋雷区。

输出
把雷盘重新输出,但是地雷周围的‘0’修改成‘0’附近的地雷的数量。

样例输入 复制
1
9
2
90
09
3
099
000
900
样例输出 复制
9
92
29
199
232
910

#include<iostream>
#include<cstring>
using namespace std;
char maz[1105][1105];
int x,all=0;
int xxx[8] = {
    
     1,-1,0,0,1,-1,1, -1};
int yyy[8] = {
    
     0,0,1,-1,1,-1 ,-1,1};
int sooo(int i, int j)
{
    
    
	
	all = 0;
	for (int k = 0; k < 8;k++)
	{
    
    
		if (maz[i + xxx[k]][j + yyy[k]] == '9')
		{
    
    
			all++;
			
	    }
		
	}
	all = all + 48;
	return all;

}
int main()
{
    
    
	int sum = 0;
	
	while (cin >> x)
	{
    
    
        sum = 0;
		if (x == 0 )
			return 0;
		memset(maz, 0, sizeof(maz));
		for (int i = 0; i < x; i++)
		{
    
    
			for (int j = 0; j < x; j++)
				cin >> maz[i][j];
		}
        for (int i = 0; i < x; i++)
		{
    
    
			for (int j = 0; j < x; j++)
			{
    
    
				if (maz[i][j] == '0')//
				{
    
    
					sooo(i, j) ;//搜索
					 maz[i][j] = char(all);
					
				}
			}

		}
		for (int i = 0; i < x; i++)
		{
    
    
			for (int j = 0; j < x; j++)
			{
    
    
				cout << maz[i][j] ;
			}
			cout << endl;
		}
	
		
	}
}

问题 B: 勘探油田
题目描述
某石油勘探公司正在按计划勘探地下油田资源。他们工作在一片长方形的地域中,首先将该地域划分为许多小正方形区域,然后使用探测设备分别探测每一块小正方形区域是否有油。若在一块小正方形区域中探测到有油,则标记为’@’,否则标记为’*’。如果两个相邻区域都为‘@’,那么它们同属于一个石油带,一个石油带可能包含很多小正方形区域,而你的任务是要确定在一片长方形地域中有多少个石油带。

所谓相邻,是指两个小正方形区域上下、左右、左上右下或左下右上同为’@’。

输入
输入数据将包含一些长方形地域数据,每个地域数据的第一行有两个正整数m和n,表示该地域为mn个小正方形所组成,如果m为0,表示所有输入到此结束。否则,后面m(1≤m≤100)行数据,每行有n(1≤n≤100)个字符,每个字符为’@’或’’,表示有油或无油。每个长方形地域中,’@’的个数不会超过100。

输出
每个长方形地域,输出油带的个数,每个油带值占独立的一行。油带值不会超过100。

样例输入 复制
1 1
*
3 5
@@*
@
@@*
1 8
@@***@
5 5
****@
@@
*@
@
@@@
@
@@**@
0 0
样例输出 复制
0
1
2
2

#include<iostream>
using namespace std;
char maz[1105][1105];//1105是我的生日,这都能查重我就emm
int x, y;//记得定义在外面(曾经的错误)
int xxx[8] = {
    
     1,-1,0,0,1,-1,1, -1};
int yyy[8] = {
    
     0,0,1,-1,1,-1 ,-1,1};
void sooo(int i, int j)
{
    
    
	if (i<0 || j<0 || i>x || j>y)//i,j这个边界条件可以想想老师上课讲的那个栈结构
	{
    
    
		return;//不能超过边界,超了就结束搜索
	}
	maz[i][j] = '*';

	for (int k = 0; k < 8;k++)
	{
    
    
		if (maz[i + xxx[k]][j + yyy[k]] == '@')//八个方向又八个方向的搜索油田
		{
    
    
			sooo(i + xxx[k], j + yyy[k]);//每次调用都会执行maz[i][j] = '*';
	    }
	}

}
int main()
{
    
    
	int sum = 0;

	while (cin >> x >> y)
	{
    
    
        sum = 0;
		if (x == 0 && y == 0)
			return 0;
		for (int i = 0; i < x; i++)
		{
    
    
			for (int j = 0; j < y; j++)
				cin >> maz[i][j];
		}
        for (int i = 0; i < x; i++)
		{
    
    
			for (int j = 0; j < y; j++)
			{
    
    
				if (maz[i][j] == '@')//遍历地图的每一个地方,如果是@那么说明有一块油田
				{
    
    
                    sooo(i, j);//搜索
					sum += 1;
				}
			}

		}
		cout << sum << endl;
	}
}

问题 C: 迷宫营救
题目描述
在1000年以前,小QQ是我国最痴情的剑客。他英俊潇洒,而且机智过人_
突然有一天,小QQ心爱的公主RED被魔王困在了一个巨大的迷宫中。小QQ听说这个消息已经是两天以后了,他知道公主在迷宫中还能坚持T天,他急忙赶到迷宫,开始到处寻找公主的下落。
时间一点一点的过去,小QQ还是无法找到公主。最后当他找到公主的时候,美丽的公主已经死了。从此小QQ郁郁寡欢,茶饭不思,一年后追随公主而去了。T_T
1000年后的今天,公主RED托梦给你,并高速你迷宫的地图和时间T,你希望你帮她判断一下当年小QQ是否有机会在给定的时间内找到公主。

输入
题目包括多组测试数据。
每组测试数据以三个整数N,M,T(0<n, m≤200, t>0)开头,分别代表迷宫的长和高,以及公主能坚持的天数。
紧接着有M行,N列字符,由".","",“P”,"S"组成。其中
“.” 代表能够行走的空地。
"
" 代表墙壁,小QQ不能从此通过。
“P” 是公主所在的位置。
“S” 是小QQ的起始位置。
每个时间段(一天)里小QQ只能选择“上、下、左、右”任意一方向走一步。
输入以0 0 0结束。
输出
如果能在规定时间内救出公主输出“YES”,否则输出“NO”。

样例输入 复制
4 4 10



S**P
0 0 0
样例输出 复制
YES
提示
纠错:“-”或者"." 代表能够行走的空地

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int sx, sy,w,h,d;
char map[1105][1105];
bool didsearch[1105][1105];
int xxx[4] = {
    
     1,-1,0,0,};
int yyy[4] = {
    
     0,0,1,-1,};
struct point
{
    
    
	int x, y, step;
};
queue<point>list;
bool search(int x, int y)
{
    
    
	//queue<point>list;
	list.push(point{
    
     x,y,0 });
	didsearch[x][y] = true;
	while (!list.empty())
	{
    
    
		point p = list.front();
		list.pop();
		if (map[p.x][p.y] == 'P')
		{
    
    
			if (p.step <= d)
			{
    
    
				return true;
			}
		}
		for (int i = 0; i < 4; i++)
		{
    
    
			int xx = p.x + xxx[i];
			int yy = p.y + yyy[i];
			if (xx >= 0 && yy >= 0 && xx < w && yy < h && didsearch[xx][yy] == false && map[xx][yy] != '*')
			{
    
    
				didsearch[xx][yy] = true;
				list.push({
    
     xx,yy,p.step + 1 });
			}
		}
	}
	return false;
}
int main()
{
    
    
	while (cin >> w >> h >> d)
	{
    
    
		if (w == 0)return 0;
		memset(didsearch,false , sizeof(didsearch));
		memset(map, 0, sizeof(map));
		int temp = w;
		w = h;
		h = temp;
		for (int i = 0; i < w; i++)
		{
    
    
			for (int j = 0; j < h; j++)
			{
    
    
				cin >> map[i][j];
				if (map[i][j] == 'S')
				{
    
    
					sx = i;
					sy = j;
				}
			}
		}
		if (search(sx, sy))
		{
    
    
			cout << "YES" << endl;

		}
		else
		{
    
    
			cout << "NO" << endl;
		}
	}
}

问题 D: 胜利大逃亡
题目描述
Ignatius被魔王抓走了,有一天魔王出差去了,这可是Ignatius逃亡的好机会.魔王住在一个城堡里,城堡是一个ABC的立方体,可以被表示成A个B*C的矩阵,刚开始Ignatius被关在(0,0,0)的位置,离开城堡的门在(A-1,B-1,C-1)的位置,现在知道魔王将在T分钟后回到城堡,Ignatius每分钟能从一个坐标走到相邻的六个坐标中的其中一个.现在给你城堡的地图,请你计算出Ignatius能否在魔王回来前离开城堡(只要走到出口就算离开城堡,如果走到出口的时候魔王刚好回来也算逃亡成功),如果可以请输出需要多少分钟才能离开,如果不能则输出-1.

在这里插入图片描述

输入
输入数据的第一行是一个正整数K,表明测试数据的数量.每组测试数据的第一行是四个正整数A,B,C和T(1<=A,B,C<=50,1<=T<=1000),它们分别代表城堡的大小和魔王回来的时间.然后是A块输入数据(先是第0块,然后是第1块,第2块…),每块输入数据有B行,每行有C个正整数,代表迷宫的布局,其中0代表路,1代表墙。

输出
对于每组测试数据,如果Ignatius能够在魔王回来前离开城堡,那么请输出他最少需要多少分钟,否则输出-1.

样例输入 复制
2
6 5 5 18
1 0 0 0 1
0 0 0 0 0
0 0 0 0 1
0 1 0 0 1
0 0 1 0 0
0 0 0 0 0
1 0 0 0 0
0 0 0 0 0
1 0 0 0 1
0 1 0 0 0
0 0 0 0 0
1 0 0 0 1
0 1 0 1 1
0 0 0 0 0
0 0 0 0 1
0 0 1 0 1
1 0 1 0 1
1 0 0 0 0
0 0 0 0 0
0 0 0 0 1
0 0 0 0 0
0 0 1 1 0
0 0 0 0 1
0 0 0 1 0
0 0 0 0 1
0 0 0 1 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 1
0 0 0 0 0
1 3 7 9
0 0 1 0 1 0 0
0 0 0 0 1 0 1
1 0 1 0 1 1 0
样例输出 复制
13
-1

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
int sx, sy, n,m,h,s;
char map[110][110][110];
bool didsearch[110][110][110];
int xxx[6] = {
    
     0,0,0,0,1,-1 };
int yyy[6] = {
    
     1,-1,0,0,0,0 };
int zzz[6] = {
    
     0,0,1,-1,0,0 };
struct point
{
    
    
	int x, y,z, step;
};
queue<point>list;
void search(int x, int y,int z)
{
    
    
	list.push(point{
    
     x,y,z,0 });
	didsearch[x][y][z] = true;
	while (!list.empty())
	{
    
    
		point p = list.front();
		list.pop();
	    if (p.x == n - 1 && p.y == m - 1 && p.z == h - 1 && p.step <= s)
		{
    
    
         cout << p.step << endl;
		 return;
		
		}
		if (p.step > s)
		{
    
    
			cout <<"-1" << endl;
			return;
			}
		for (int i = 0; i < 6; i++)
		{
    
    
			int xx = p.x + xxx[i];
			int yy = p.y + yyy[i];
			int zz = p.z + zzz[i];
			if (xx >= 0 && xx < n && yy >= 0 && yy < m && zz >= 0 && zz < h && didsearch[xx][yy][zz] == false && map[xx][yy][zz] == '0' )
			{
    
    
				didsearch[xx][yy][zz] = true;
				list.push({
    
     xx,yy,zz,p.step + 1 });
		
			}

		}
	}
	cout << -1 << endl;
}
int main()
{
    
    
	int X; cin >> X;
	while (X--)
	{
    
    
		cin >> n >> m >> h>>s;
		memset(didsearch, false, sizeof(didsearch));
		memset(map, 0, sizeof(map));
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				for (int u = 0; u < h; u++)
					cin >> map[i][j][u];
		search(0, 0, 0);
	}
}

Guess you like

Origin blog.csdn.net/AAliuxiaolei/article/details/106276596