洛谷 P1825 Corn Maze S

题意翻译

奶牛们去一个 N×M 玉米迷宫,2≤N≤300,2≤M≤300。

迷宫里有一些传送装置,可以将奶牛从一点到另一点进行瞬间转移。这些装置可以双向使用。

如果一头奶牛处在这个装置的起点或者终点,这头奶牛就必须使用这个装置,奶牛在传送过后不会立刻进行第二次传送,即不会卡在传送装置的起点和终点之间来回传送。

玉米迷宫除了唯一的一个出口都被玉米包围。

迷宫中的每个元素都由以下项目中的一项组成:

  1. 玉米,# 表示,这些格子是不可以通过的。
  2. 草地,. 表示,可以简单的通过。
  3. 传送装置,每一对大写字母 A 到 Z 表示。
  4. 出口,= 表示。
  5. 起点, @ 表示

输入格式

第一行:两个用空格隔开的整数 N 和M。

第 2∼N+1 行:第 i+1 行描述了迷宫中的第 i 行的情况(共有M个字符,每个字符中间没有空格)。

输出格式

一个整数,表示起点到出口所需的最短时间。

 样例

样例1

输入

5 6
###=##
#.W.##
#.####
#.@W##
######

输出
3

样例2

输入

30 16
##############=#
#A...........A.#
#.B...........B#
#C...........C.#
#.D...........D#
#E...........E.#
#.F...........F#
#G...........G.#
#.H...........H#
#I...........I.#
#.J...........J#
#K...........K.#
#.L...........L#
#M...........M.#
#.N...........N#
#O...........O.#
#.P...........P#
#Q...........Q.#
#.R...........R#
#S...........S.#
#.T...........T#
#U...........U.#
#.V...........V#
#W...........W.#
#.X...........X#
#Y...........Y.#
#.Z...........Z#
#.##############
#.............@#
################

输出 

42

样例3

输入

8 6
###=##
#..W.#
#....#
##@..#
#....#
#....#
#..W.#
######

输出 

5

思路:

1.很bfs的一道题,就是传送装置需要特别处理一下,每次到传送装置的地点的时候就启用下面的函数找到另一个装置所在地

void BBC()
{
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			if(g[a][b]==g[i][j])
			{
				if(a!=i||b!=j)
				{
				    a=i,b=j;
				    return;
				}
			}
}

2.要注意每个装置使用可能不止一次,就像样例3那样,所以每次标状态时标传送的出发点的坐标

AC code

#include <iostream>
#include <cstring>
using namespace std;

typedef pair<int,int>PII;
int n,m,s1,s2,e1,e2,a,b;
PII q[900001];数组模拟队列(比直接调用queue快点)
int dist[301][301];记录每个点距离起点的步数
int st[301][301];记录每个点的状态,0表示没走过,1表示已走过
char g[301][301];记录地图

处理传送装置的函数
void BBC()
{
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(g[a][b]==g[i][j])
			{
				if(a!=i||b!=j)
				{
				    a=i,b=j;
				    return;
				}
			}
		}
	}
}


int bfs(int x,int y)
{
	int dx[]={0,1,-1,0};
	int dy[]={1,0,0,-1};
	q[0]={x,y};起点入队
	dist[x][y]=0;
	st[x][y]=1;
	int tt=0,ll=0;
	
	while(ll<=tt)
	{
		PII t=q[ll++];队头出队
		for(int i=0;i<4;i++)
		{
			a=t.first+dx[i],b=t.second+dy[i];
			if(a<1||a>n||b<1||b>m) continue; 越界
			if(g[a][b]=='#') continue;
			if(st[a][b]==1) continue;
			if(g[a][b]<='Z'&&g[a][b]>='A')
			{
				st[a][b]=1; 这里只记录传送位置出发点的状态
				BBC();
				dist[a][b]=dist[t.first][t.second]+1;
			    q[++tt]={a,b};
			}
			else{
				st[a][b]=1; 
				dist[a][b]=dist[t.first][t.second]+1;
				q[++tt]={a,b};
			    if(dist[s2][e2]>0) return dist[s2][e2];
		    }
		}
	}
}

int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%s",g[i]+1);
	int k=0;
    找起点和终点
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(g[i][j]=='@') s1=i,e1=j;
			if(g[i][j]=='=') s2=i,e2=j;
		}
	}
	int res=bfs(s1,e1);
	printf("%d",res);
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值