2024牛客暑期多校训练营1 I Mirror Maze

链接:登录—专业IT笔试面试备考平台_牛客网
来源:牛客网
 

题目描述

There is an n×m mirror maze, where there is a mirror on each grid. The mirrors are in one of the following four types:

  • ``-'', the light from above or below will be reflected back, the light from left or right will continue going forward without being reflected, respectively;
  • ``|'', the light from left or right will be reflected back, the light from above or below will continue going forward without being reflected, respectively;
  • ``/'', the light from left, right, above, below will be reflected to go above, below, left, right, respectively;
  • ``\', the light from left, right, above, below will be reflected to go below, above, right, left, respectively.

Now there are q light sources. Little G, the believer of the light, wants to know the numbers of different mirrors the emitted light will be reflected by within sufficient time for each light source.

输入描述:

The first line contains two integers n,m(1≤n,m≤1000), denoting the size of the mirror maze.

Each of the following nnn lines contains a string of length mmm, where the jjj-th character in the iii-th line Si,j​(Si,j​∈{∣,−,/,\}) denotes the mirror on grid (i,j).

The next line contains an integer q (1≤q≤105)q, denoting the number of light sources.

Each of the following qqq lines contains two integers u(1≤u≤n),v(1≤v≤m) and a string dir (dir∈{above,below,left,right}), denoting that a light source is on grid (u,v) and emits light going along the dirdirdir direction. Specifically, the light will not be influenced by the mirror on grid (u,v) initially.

输出描述:

Output q lines each containing one integer, denoting the number of different mirrors the emitted light will be reflected by within sufficient time for each light source.

示例1

输入

2 3
/\-
\/|
2
1 2 below
2 2 right

输出

4
2

说明

· For the first light, it will be reflected by the mirrors at (2,2),(2,1),(1,1),(1,2)(2,2), (2,1), (1,1), (1,2)(2,2),(2,1),(1,1),(1,2) repeatedly and stay in the mirror maze.
· For the second light, it will be reflected by (2,3)(2,3)(2,3) and go back to (2,2)(2,2)(2,2), then reflected by (2,2)(2,2)(2,2), go below, and get away from the mirror maze.

题目大意:有一个 n × m 的矩形镜子迷宫,镜子有 “\, /, -, |” 四种,每种镜子有特 定的光线反射方向,注意直接通过镜子的情况不算被反射。 有 q 个询问,每个询问给定一个点光源 (x, y, dir),表示在 (x, y) 位置向 dir 方向发射一束光线,问经过足够的时间之后,这束光线被多少个不 同的镜子反射过。 1 ≤ n, m ≤ 1000, 1 ≤ q ≤ 10^{5}

思路:因为光路可逆,所以不可能有光束分叉或者汇合的情况,所以所有的光 束会构成若干个环和若干条链。 所以我们要做的就是把这些光环和光链抽出来,然后预处理出每个点光 源的答案,询问就查表 O(1) 回答即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n,m,t;
char ch[1005][1005];
int ans[1005][1005][5],vis[1005][1005][5];
int dir[5][2]={0,0,-1,0,1,0,0,-1,0,1};
int fun(int w,char c){
	if(w==1){
		if(c=='-') return 2;
		else if(c=='\\') return 3;
		else if(c=='/') return 4;
		else return 1;
	}else if(w==2){
		if(c=='-') return 1;
		else if(c=='\\') return 4;
		else if(c=='/') return 3;
		else return 2;
	}else if(w==3){
		if(c=='|') return 4;
		else if(c=='\\') return 1;
		else if(c=='/') return 2;
		else return 3;
	}else{
		if(c=='|') return 3;
		else if(c=='\\') return 2;
		else if(c=='/') return 1;
		else return 4;
	}
}
void dfs(int x,int y,int w,int cnt){
	int tx=x+dir[w][0],ty=y+dir[w][1];
	if(tx<1 || tx>n || ty<1 || ty>m) return ;
	if((w==1 || w==2) && ch[tx][ty]=='|') dfs(tx,ty,w,cnt);
	else if((w==3 || w==4) && ch[tx][ty]=='-') dfs(tx,ty,w,cnt);
	else if(vis[tx][ty][0]) dfs(tx,ty,fun(w,ch[tx][ty]),cnt);
	else if(!vis[tx][ty][0]){
		vis[tx][ty][0]=1;
		dfs(tx,ty,fun(w,ch[tx][ty]),cnt+1);
		vis[tx][ty][0]=0;
	}
	if(w==1) ans[tx][ty][2]=cnt;
	else if(w==2) ans[tx][ty][1]=cnt;
	else if(w==3) ans[tx][ty][4]=cnt;
	else if(w==4) ans[tx][ty][3]=cnt;
}
int DFS(int x,int y,int w,int cnt){ 
	if(vis[x][y][w]) return ans[x][y][w]=cnt;
	vis[x][y][w]=1;
	int tx=x+dir[w][0],ty=y+dir[w][1];
	if((w==1 || w==2) && ch[tx][ty]=='|') return ans[x][y][w]=DFS(tx,ty,w,cnt);
	else if((w==3 || w==4) && ch[tx][ty]=='-') return ans[x][y][w]=DFS(tx,ty,w,cnt);
	else if(vis[tx][ty][0]) return ans[x][y][w]=DFS(tx,ty,fun(w,ch[tx][ty]),cnt);
	else{
		vis[tx][ty][0]=1;
		ans[x][y][w]=DFS(tx,ty,fun(w,ch[tx][ty]),cnt+1);
		vis[tx][ty][0]=0;
		return ans[x][y][w];
	}
}
signed main()
{
	IOS
	cin >> n >> m;
	//预处理
	//初始化 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin >> ch[i][j];
			for(int k=1;k<=4;k++){
				ans[i][j][k]=-1;
			}
		}
	}
	//判链 
	for(int i=1;i<=m;i++){
		vis[0][i][0]=1;
		dfs(0,i,2,0);
		vis[0][i][0]=0;
		vis[n+1][i][0]=1;
		dfs(n+1,i,1,0);
		vis[n+1][i][0]=0;
	}
	for(int i=1;i<=n;i++){
		vis[i][0][0]=1;
		dfs(i,0,4,0);
		vis[i][0][0]=0;
		vis[i][m+1][0]=1;
		dfs(i,m+1,3,0);
		vis[i][m+1][0]=0;
	}
	//判环 
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			for(int k=1;k<=4;k++){
				if(ans[i][j][k]==-1) ans[i][j][k]=DFS(i,j,k,0);
			}
		}
	}
	cin >> t;
	while(t--){
		int x,y,w=0;
		string s;
		cin >> x >> y >> s;
		if(s=="above") w=1;
		else if(s=="below") w=2;
		else if(s=="left") w=3;
		else if(s=="right") w=4;
		cout << ans[x][y][w] << endl;
	}
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值