2024牛客暑期多校训练营1 - I. Mirror Maze
题目大意:一个由四种镜面(| - / \
)组成的矩阵,根据镜面的方向反射光线。问坐标 \((x,y)\) 处向某方向射入一束光线后(此光线会直接穿过此位置 \((x,y)\) 的镜面),一共会反射(直接穿过的不算)到多少个不同(一个坐标算一个镜面)的镜面。
总体思路为预处理出每一个坐标向每一个位置发射光线的答案。
处理“不同”的镜面可以直接用 set
记录坐标并去重,最后求 size
。
由于光路可逆,所以光路没有分叉或汇合的情况,故所有的路径一定是环或链。
先考虑链的情况:因为链的尽头一定是边界,所以从四个边界向内发射光线。通过光路可逆将“抵达该坐标时朝向某方向”转化为“离开某坐标时朝向它的反方向”,这样就可以避免递归(会爆栈)或手动堆栈(懒得写)。即在遍历一条光路的时候记录的时它的反向光路的答案。
再考虑环的情况。去除所有的链以后,剩下的还未被访问到的点及方向(注意是某个点的某个方向,不单指这个点)就都在环内。在这些地方和方向再分别发射一条光线进行遍历。当走到已访问过的点时说明走完了一个完整的环。途中记录的环大小(即 set
的大小)就是中途每一个点及方向的答案。
注意记录访问需要单独一个 vst
数组,因为查链的时候可能出现在一条链内但答案是 \(0\) 的情况。
代码如下:
#include<set> #include<map> #include<cstdio> #include<string> #include<vector> #include<cstring> #include<iostream> #include<unordered_map> using namespace std; const int N=1005; int n,m,q; char str[N][N]; int maze[N][N]; const int rotation[10][10]={ {0,0,0,0,0}, {0,1,2,4,3}, // '|' {0,2,1,3,4}, // '-' {0,4,3,2,1}, // '/' {0,3,4,1,2} // '\' }; const int trans_x[10]={0,-1,1,0,0}; const int trans_y[10]={0,0,0,-1,1}; const int rev_direction[10]={0,2,1,4,3}; map<string,int> DIR={{"above",1},{"below",2},{"left",3},{"right",4}}; map<char,int> MIR={{'|',1},{'-',2},{'/',3},{'\\',4}}; struct Rain{ int x,y; int dir; // 1↑ 2↓ 3← 4→ | 进入方向 void step() //先转再走 { dir=rotation[maze[x][y]][dir]; x+=trans_x[dir],y+=trans_y[dir]; return; } bool chg_dir(){return dir!=rotation[maze[x][y]][dir];} //是否改变方向 bool check(){return x>=1&&x<=n && y>=1&&y<=m;} }; int rev_dir(int dir){return rev_direction[dir];} int ans[N][N][6]; bool vst[N][N][6]; void Biu(Rain light) { set<pair<int,int>> reflect; while(light.check()) { ans[light.x][light.y][rev_dir(light.dir)]=reflect.size(); vst[light.x][light.y][rev_dir(light.dir)]=true; if(light.chg_dir()) reflect.insert({light.x,light.y}); light.step(); } return; } void Prework_chain() { for(int i=1;i<=n;i++) { Biu({i,1,4}); Biu({i,m,3}); } for(int i=1;i<=m;i++) { Biu({1,i,2}); Biu({n,i,1}); } return; } void Pu(Rain light) { set<pair<int,int>> reflect; vector<Rain> path; while(!vst[light.x][light.y][rev_dir(light.dir)]) { vst[light.x][light.y][rev_dir(light.dir)]=true; if(light.chg_dir()) reflect.insert({light.x,light.y}); path.push_back(light); light.step(); if(!light.check()) return; } for(Rain x:path) ans[x.x][x.y][rev_dir(x.dir)]=reflect.size(); return; } void Prework_cycle() { for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) for(int k=1;k<=4;k++) if(!vst[i][j][k]) Pu({i,j,rev_dir(k)}); return; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%s",str[i]+1); for(int j=1;j<=m;j++) maze[i][j]=MIR[str[i][j]]; } Prework_chain(); Prework_cycle(); scanf("%d",&q); for(int i=1;i<=q;i++) { int x,y; scanf("%d%d",&x,&y); string dir; cin>>dir; printf("%d\n",ans[x][y][DIR[dir]]); } return 0; }
本文采用 「CC-BY-NC 4.0」 创作共享协议,转载请注明作者及出处,禁止商业使用。
作者:Jerrycyx,原文链接:https://www.cnblogs.com/jerrycyx/p/18447987
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步