10-广搜

这是一个关于迷宫问题的系列题目,涉及到不同的解题策略。第一题使用宽度优先搜索(BFS)求解最小步数,第二题同样利用BFS记录从起点到终点的路径,第三题通过BFS寻找城堡中的房间数量和最大房间面积,第四题则考虑了棋类游戏中棋子的特殊走法,求解到达目标点的最少步数。这些题目均涉及到了图的遍历和搜索算法的应用。
摘要由CSDN通过智能技术生成

1、最小步数

1252:走迷宫

【题目描述】

一个迷宫由R行C列格子组成,有的格子里有障碍物,不能走;有的格子是空地,可以走。

给定一个迷宫,求从左上角走到右下角最少需要走多少步(数据保证一定能走到)。只能在水平方向或垂直方向走,不能斜着走。

【输入】

第一行是两个整数,R和C,代表迷宫的长和宽。( 1<= R,C <= 40)

接下来是R行,每行C个字符,代表整个迷宫。

空地格子用‘.’表示,有障碍物的格子用‘#’表示。

迷宫左上角和右下角都是‘.’。

【输出】

输出从左上角走到右下角至少要经过多少步(即至少要经过多少个空地格子)。计算步数要包括起点和终点。

【输入样例】

5 5

..###

#....

#.#.#

#.#.#

#.#..

【输出样例】

9

<代码>

#include<bits/stdc++.h>
using namespace std;
const int N=105;
int a[N][N],n,m,ans,d[N][N];
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
queue<pair<int,int> >q;
void bfs()
{
	d[1][1]=1;a[1][1]=0;
	q.push(make_pair(1,1));
	while(q.size())
	{
		pair<int,int> u=q.front();q.pop();
		if(u.first==n&&u.second==m)break;
		for(int i=0;i<4;i++)
		{
			int xx=u.first+dx[i],yy=u.second+dy[i];
			if(xx<1||xx>n||yy<1||yy>m||a[xx][yy]==0)continue;
			q.push(make_pair(xx,yy));
			d[xx][yy]=d[u.first][u.second]+1;
			a[xx][yy]=0;
		}
	}
	cout<<d[n][m];
}
int main()
{
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=m;j++)
	  {
		char c;cin>>c;
		if(c=='.')a[i][j]=1;
	  }
	bfs();
	return 0;
}

2、记录路径

1255 迷宫问题

【题目描述】

定义一个二维数组:

int maze[5][5] = {

0,1,0,0,0,

0,1,0,1,0,

0,0,0,0,0,

0,1,1,1,0,

0,0,0,1,0,

};

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。

【输入】

一个5 × 5的二维数组,表示一个迷宫。数据保证有唯一解。

【输出】

左上角到右下角的最短路径,格式如样例所示。

【输入样例】

0 1 0 0 0

0 1 0 1 0

0 0 0 0 0

0 1 1 1 0

0 0 0 1 0

【输出样例】

(0, 0)

(1, 0)

(2, 0)

(2, 1)

(2, 2)

(2, 3)

(2, 4)

(3, 4)

(4, 4)

<代码>

#include<bits/stdc++.h>
using namespace std;
int a[6][6],h,t,pre[30];
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
pair<int,int>q[30];
void bfs()
{
	q[++t]=make_pair(1,1);
	a[1][1]=1;
	while(h<t)
	{
		++h;
		int x=q[h].first,y=q[h].second;
		for(int i=0;i<4;i++)
		{
			int xx=x+dx[i],yy=y+dy[i];
			if(xx<1||xx>5||yy<1||yy>5||a[xx][yy])continue;
			q[++t]=make_pair(xx,yy);
			pre[t]=h;//前驱
			a[xx][yy]=1;
			if(xx==5&&yy==5)return;
		}
	}
}
void print(int k)
{
	if(k==0)return;
    print(pre[k]);
    printf("(%d, %d)\n",q[k].first-1,q[k].second-1);
}
int main()
{
	for(int i=1;i<=5;i++)
	 for(int j=1;j<=5;j++)
	   cin>>a[i][j];
	bfs();
	print(t);
	return 0;
}

3、条件转换

1250 The Castle

【题目描述】

一座城堡被分成m*n个方块(m≤50,n≤50),每个方块可有0~4堵墙(0表示无墙)。下面示出了建筑平面图:

图中的加粗黑线代表墙。几个连通的方块组成房间,房间与房间之间一定是用黑线(墙)隔开的。

现在要求你编一个程序,解决以下2个问题:

1、该城堡中有多少个房间?

2、最大的房间有多大?

【输入】

平面图用一个数字表示一个方块(第1个房间用二进制1011表示,0表示无东墙,用十进制11表示)。

第一行一个整数m(m≤50),表示房子南北方向的长度。

第二行一个整数n(n≤50),表示房子东西方向的长度。

后面的m行,每行有n个整数,每个整数都表示平面图对应位置的方块的特征。每个方块中墙的特征由数字P来描述(0≤P≤15)。数字P是下面的可能取的数字之和:

1(西墙 west)

2(北墙 north)

4(东墙 east)

8(南墙 south)

室内的墙被定义两次: 例如方块(1,1)中的南墙也被位于其南面的方块(2,1)定义了一次。

建筑中至少有两个房间。

【输出】

第1行:一个整数,表示房间总数;

第2行:一个整数,表示最大房间的面积(方块数)。

【输入样例】

4

7

11 6 11  6  3 10  6

7  9  6 13  5 15  5

1 10 12  7 13  7  5

13 11 10 8 10 12 13

【输出样例】

5

9

<代码>

#include<bits/stdc++.h>
using namespace std;
const int N=100;
int a[N][N],b[N][N],n,m,ans,mx;
int dx[4]={0,-1,0,1},dy[4]={-1,0,1,0};
struct node{int x,y;};
queue<node>q;
void bfs(int x,int y)
{
	q.push((node){x,y});
	ans++;
	b[x][y]=1;
	int res=1;
	while(q.size())
	{
		x=q.front().x,y=q.front().y;q.pop();
		for(int i=0;i<4;i++)
		{
			int flag=(a[x][y]>>i)&1;
			int xx=x+dx[i],yy=y+dy[i];
			if(xx<1||xx>n||yy<1||yy>m||flag||b[xx][yy]==1)continue;
			q.push((node){xx,yy});
			b[xx][yy]=1;
			res++;
		}
	}
	mx=max(mx,res);
}
int main()
{
	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(!b[i][j])
		 bfs(i,j);
		
	cout<<ans<<endl<<mx<<endl;
	return 0;
}

4、增量数组变化

1330 【例8.3】最少步数

【题目描述】

在各种棋中,棋子的走法总是一定的,如中国象棋中马走“日”。有一位小学生就想如果马能有两种走法将增加其趣味性,因此,他规定马既能按“日”走,也能如象一样走“田”字。他的同桌平时喜欢下围棋,知道这件事后觉得很有趣,就想试一试,在一个(100×100)的围棋盘上任选两点A、B,A点放上黑子,B点放上白子,代表两匹马。棋子可以按“日”字走,也可以按“田”字走,俩人一个走黑马,一个走白马。谁用最少的步数走到左上角坐标为(1,1)的点时,谁获胜。现在他请你帮忙,给你A、B两点的坐标,想知道两个位置到(1,1)点可能的最少步数。

【输入】

A、B两点的坐标。

【输出】

最少步数。

【输入样例】

12 16

18 10

【输出样例】

8

9

<代码>

#include<bits/stdc++.h>
using namespace std;
const int N=110;
int a[N][N],n,m,A,B,C,D;
int dx[12]={-2,-2,-2,-2,-1,1,2,2,2,2,1,-1};
int dy[12]={-2,-1,1,2,2,2,2,1,-1,-2,-2,-2};
struct node{int x,y;};
queue<node>q;
void bfs()
{
	a[1][1]=1;
	q.push((node){1,1});
	while(q.size())
	{
		int x=q.front().x,y=q.front().y;q.pop();
		for(int i=0;i<12;i++)
		{
			int xx=x+dx[i],yy=y+dy[i];
			if(xx<1||xx>100||yy<1||yy>100||a[xx][yy])continue;
			a[xx][yy]=a[x][y]+1;
			q.push((node){xx,yy});
			if(a[A][B]&&a[C][D])return;
		}
	}
}
int main()
{
	cin>>A>>B>>C>>D;
	bfs();
	cout<<a[A][B]-1<<endl<<a[C][D]-1<<endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值