JZOJ 青铜莲花池(bfs-广度优先搜索)

本文介绍了如何使用广度优先搜索(BFS)算法解决一个关于路径规划的问题,即宁智贤在矩形人工湖的荷叶间跳跃到达目标所需最小跳跃次数。题目中给出了湖泊的布局和跳跃规则,通过读取输入数据,计算跳跃方向数组,然后进行BFS搜索,最终找到最短路径并输出跳跃次数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Farmer John为了满足宁智贤对美的享受而安装了人工湖。矩形的人工湖分成M行 N N N ( 1 < = M < = 30 ; 1 < = N < = 30 ) (1 <= M <= 30; 1 <= N <= 30) (1<=M<=30;1<=N<=30) 的方形小格子。有些格子有美丽的荷叶,有些有岩石,剩下的格子有的只是美丽的蓝色湖水。 宁智贤通过从一片荷叶跳到另一片荷叶上来练习芭蕾。它现在正站在一片荷叶上(看输入数据了解具体位置)。它希望通过在荷叶上跳跃来到达另一片荷叶。它既不能跳到水里也不能跳到岩石上。 只有新手才会感到吃惊:宁智贤的跳跃有点类似国际象棋中马那样的移动,在一个方向上(如水平方向)移动 M 1 ( 1 < = M 1 < = 30 ) M1(1 <= M1 <= 30) M1(1<=M1<=30)“格”,然后再在另一个方向上(如竖直方向)移动 M 2 ( 1 < = M 2 < = 30 ; M 1 ! = M 2 ) M2 (1 <= M2 <= 30; M1 != M2) M2(1<=M2<=30;M1!=M2) 格,所以宁智贤有时可能有多达8中的跳跃选择。
给出池塘的构造以及宁智贤跳跃的形式,找出宁智贤从一个位置移动到另一个位置所需的最小的跳跃次数。这个跳跃对于所给的测试数据总是可能的。

Input

1 1 1 行: 四个空格分开的整数: M , N , M 1 , 和 M 2 M, N, M1, 和 M2 M,N,M1,M2

2 2 2 M + 1 M+1 M+1行: 第i+1行用N个空格分开的整数描述池塘第 i i i 行, 0 0 0 表示水, 1 1 1 表示荷叶,2表示岩石,3表示宁智贤现在站的那块荷叶,4表示跳跃的终点。

Output

一个整数,是宁智贤从一块荷叶跳到另一块荷叶所需的最小的跳跃数。

Data

保证 1 ≤ M ≤ 30 1≤M≤30 1M30 1 ≤ N ≤ 30 1≤N≤30 1N30
时间限制: 1 s 1s 1s
空间限制: 256 M B 256MB 256MB

Solution

  • 猛然发现好像又是一道板子
  • 首先根据题意我们可以很轻松地算出方向数组,在读入二维数组地时候记录起点,塞进队列里,当然也要记录一下终点;
  • 然后就是一个基本的bfs,详情见代码

Code

#include <bits/stdc++.h>
using namespace std;
int a[10000][10000]={};
struct node
{
	int x;
	int y;
	int s;
}q[1000000]={};
int main()
{
	freopen("input.in","r",stdin);
	freopen("output.out","w",stdout);
	int n,m,m1,m2;
	int head=1,tail=0;
	int endx,endy;
	cin >> n >> m >> m1 >> m2;
	int fx[8]={m2,m2,-m2,-m2,m1,m1,-m1,-m1};  //处理方向数组
	int fy[8]={m1,-m1,m1,-m1,m2,-m2,m2,-m2};
	for (int i=1;i<=n;i++)
	 for (int j=1;j<=m;j++)
	 {
	 	int x;
	 	cin >> x;
	 	if (x==1) a[i][j]=0;  //可以走的地方
	 	if (x==0 || x==2) a[i][j]=1;  //不可以走的地方
	 	if (x==3)  //起点
	 	{
	 		a[i][j]=1;
	 		q[++tail].x=i;
	 		q[tail].y=j;
	 		q[tail].s=0;
		}
		if (x==4)  //终点
		{
			endx=i;
			endy=j;
			a[i][j]=0;
		}
	 }
	for (head=1;head<=tail;head++)
	{
		for (int i=0;i<8;i++)
		{
			int xx=q[head].x+fx[i],yy=q[head].y+fy[i];  //向8个方向走
			if (xx<1 || xx>n || yy<1 || yy>m) continue;  //判断边界
			if (a[xx][yy]==0)  //当前位置可以走
			{
				a[xx][yy]=1;  //标记走过
				q[++tail].x=xx;  //塞进队列
				q[tail].y=yy;
				q[tail].s=q[head].s+1;  //得到走到当前点的步数
				if (xx==endx && yy==endy)  //走到终点
				{
					cout << q[tail].s;  //输出步数
					return 0;
				}
			}
		}
	}
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值