面对这样小的数据范围,为什么要写搜索?于是我来写一个纯粹的模拟。这题不至于评绿吧?
大致的思路就是枚举每一个可能的入射方向,暴力模拟光的传播过程,并在这个过程中记录经过的镜面,进行判断。
我认为这题唯一复杂的地方在于对光的反射方向的处理,有一些题解中用了分类讨论,这明显太复杂了,于是可以使用映射来进行记录,方法如下:
为了方便论述,这里先定义以下的方向编号:

1 2
| int dx[4]={0,1,0,-1}; int dy[4]={1,0,-1,0};
|
然后画个图分析一下(画图真的非常重要!):

注:蓝线是镜子,黑线是入射光线,红线是反射光线,数字表示方向编号。
于是用 mp[m][d]
表示方向为 d
的光线经平面镜 m
反射后的方向,顺便把空格方向不变也定义了:
1 2 3
| mp['/' ][0]=3;mp['/' ][1]=2;mp['/' ][2]=1;mp['/' ][3]=0; mp['\\'][0]=1;mp['\\'][1]=0;mp['\\'][2]=3;mp['\\'][3]=2; mp['.' ][0]=0;mp['.' ][1]=1;mp['.' ][2]=2;mp['.' ][3]=3;
|
接下来直接模拟,注意用标记数组防止形成死循环,详见代码(不要抄袭啊,建议改变一下方向数组的定义,自己试着重新写一下)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
#include<bits/stdc++.h> #define int long long using namespace std; inline int min(int __,int ___){return __<=___?__:___;} inline int max(int __,int ___){return __>=___?__:___;} #define inf 0x3f3f3f3f3f3f3f3fll
int n,m; char c[300][300]; int dx[4]={0,1,0,-1}; int dy[4]={1,0,-1,0}; map<char,map<int,int> >mp; struct S{ int x,y,d; }; map<int,bool>vis; bool gridvis[300][300]; int sum,tot; string ans1[40001]; int ans2[40001],ans; S move(S now){ S ss=now; ss.x+=dx[mp[c[now.x][now.y]][now.d]]; ss.y+=dy[mp[c[now.x][now.y]][now.d]]; ss.d=mp[c[now.x][now.y]][now.d]; if(c[now.x][now.y]!='.'){ tot+=1-gridvis[now.x][now.y]; gridvis[now.x][now.y]=1; } return ss; } bool check_ok(S now){ vis.clear();tot=0; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ gridvis[i][j]=false; } } while(true){ now=move(now); if(tot==sum)return true; if(vis[now.x*10000+now.y*10+now.d])return false; vis[now.x*10000+now.y*10+now.d]=true; if(now.x>n||now.x<1||now.y>m||now.y<1){ return false; } } return false; } void solve(){ ans=0; cin>>n>>m; for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ cin>>c[i][j]; if(c[i][j]!='.'){ sum++; } } } for(int i=1;i<=n;i++){ if(check_ok({i,1,0})){ ans1[++ans]="W",ans2[ans]=i; } } for(int i=1;i<=m;i++){ if(check_ok({1,i,1})){ ans1[++ans]="N",ans2[ans]=i; } } for(int i=1;i<=n;i++){ if(check_ok({i,m,2})){ ans1[++ans]="E",ans2[ans]=i; } } for(int i=1;i<=m;i++){ if(check_ok({n,i,3})){ ans1[++ans]="S",ans2[ans]=i; } } cout<<ans<<endl; for(int i=1;i<=ans;i++){ cout<<ans1[i]<<ans2[i]<<" "; } cout<<endl; } signed main(){ #ifdef USE_FILE_IO freopen("code.in","r",stdin); freopen("code.out","w",stdout); #endif mp['/' ][0]=3;mp['/' ][1]=2;mp['/' ][2]=1;mp['/' ][3]=0; mp['\\'][0]=1;mp['\\'][1]=0;mp['\\'][2]=3;mp['\\'][3]=2; mp['.' ][0]=0;mp['.' ][1]=1;mp['.' ][2]=2;mp['.' ][3]=3; int t; t=1; while(t--){ solve(); } return 0; }
|