难缠的值周生
【问题描述】
小 P 上学总是迟到,迟到了以后常常会被值周生发现。被值周生发现就会给
他所在的班级扣分,被扣了分不免要挨班主任的训,这令小 P 很不爽。不过,聪
明的他经过观察发现,值周生通常会站在固定的位置,并且他们都很笨,只会向
固定的同一个方向看。于是小 P 经过潜心研究,把值周生的站位和方向以及学校
的地形绘成一张地图,你的任务是编写一个程序,帮助小 P 找出一条路从大门到
达教室并且不被值周生发现。
【输入文件】
输入文件的第一行是两个整数 N,G,代表学校是一个N × N的正方形,其
中有 G 个值周生。
接下来输入一个 N × N 的矩阵,代表学校。其中.代表空地,X(大写英文字
母)代表墙,E 代表学校的大门,小 P 将从这里进入学校,C 代表教室,小 P 到
达这里就胜利了。数字代表值周生,数字的值代表值周生的编号,显然值周生不
能穿墙透视,但是小 P 也不能翻墙或者站到墙上去。
接下来有 G 行,每行包含一个数字Gi 和一个字母,代表第 Gi 个值周生的朝
向。其中 N 表示北,S 表示南,E 表示东,W 表示西。显然,如果你撞上值周
生(走到值周生所在的格子上),也会被值周生发现。
【输出文件】
输出文件包含任意一个行走方案,每行一个字母,表示小P 每步走的方向。
如果无论小P 怎么走都不能不被值周生发现的走到教室,则输出一行整数-1。
【样例输入】
5 3
..E.1
...XX
.2.X.
.C.X.
...X3
1 E
2 E
3 W
没错这样一道题确实是冬令营的题,没错而且方法就是你第一眼看出的bfs
但是,但是,我还是错了很久,然而,当我拿到数据的时候,千言万语汇成一句话:吔屎了出题人
首先我们看一个史上最短的AC代码
1 #include<cstdio>
2 int main(){
3 freopen("guard.in","r",stdin);
4 freopen("guard.out","w",stdout);
5 puts("-1");}
没错所有数据的答案是-1,所以就算你bfs再精妙,只要你忘记输出-1,那就GG
然后更有趣的地方来了
我来展示一波数据3
10 2
....G.....
2.........
..........
..1.......
..........
....C.....
..........
..........
..........
..........
1 N
2 E
看出什么没,看出什么没????没错,题干所说的E不见了,好神奇是不是,所以你的程序就会一直少读入一个或者找错起点,是不是很神奇
所以吔屎了出题人QAQ
-------------------------------------------------------------------
好了正经点讲一讲题解,这题的做法就是BFS,特殊处理就是不要用STL的队列,手写一个队列记录一个前驱,另外就是处理视线重合和围墙两种不同的情况
然后就没了
1 #include<cstdio>
2 #include<cstring>
3 #include<algorithm>
4 #include<iostream>
5 #include<queue>
6 #include<cstdlib>
7 #include<cmath>
8 #define maxn 40
9 using namespace std;
10
11 struct node{
12 int x,y,pre;
13 };//d:0=N 1=S 2=W 3=E
14 const int dx[]={-1,1,0,0},dy[]={0,0,-1,1};
15 int n,m,sx,sy,fx,fy,g,tot;
16 int map[maxn][maxn],gx[maxn],gy[maxn],ans[maxn];
17 node q[500005];
18
19 int read(){
20 int xx=0,ff=1;char ch=getchar();
21 while(ch<'0'||ch>'9'){if(ch=='-')ff=-1;ch=getchar();}
22 while(ch>='0'&&ch<='9'){xx=xx*10+ch-'0';ch=getchar();}
23 return xx*ff;
24 }
25
26 int check(int x,int y){
27 if(x<1||x>n||y<1||y>n)return false;
28 return true;
29 }
30
31 void del(int num,int dir){
32 int nx=gx[num],ny=gy[num];
33 while(check(nx,ny)){
34 map[nx][ny]=1;
35 nx+=dx[dir];ny+=dy[dir];
36 if(map[nx][ny]==2)break;
37 }
38 }
39
40 void fre(){
41 freopen("guard.in","r",stdin);
42 freopen("guard.out","w",stdout);
43 }
44
45 void init(){
46 n=read();g=read();
47 for(int i=1;i<=n;i++){
48 for(int j=1;j<=n;j++){
49 char ch=getchar();int gg;
50 while(ch!='G'&&ch!='E'&&ch!='.'&&ch!='C'&&(ch<'0'||ch>'9')&&ch!='X')ch=getchar();
51 if(ch=='.')continue;
52 if(ch=='X')map[i][j]=2;
53 if(ch=='C')fx=i,fy=j;
54 if(ch=='E'||ch=='G')sx=i,sy=j;
55 if(ch>='1'&&ch<='9'){
56 gg=ch-'0';gx[gg]=i;gy[gg]=j;
57 }
58 }
59 }
60 for(int i=1;i<=g;i++){
61 int gg;char ch;
62 gg=read();ch=getchar();
63 while(ch!='N'&&ch!='W'&&ch!='S'&&ch!='E')ch=getchar();
64 if(ch=='N'){del(gg,0);}
65 if(ch=='S'){del(gg,1);}
66 if(ch=='W'){del(gg,2);}
67 if(ch=='E'){del(gg,3);}
68 }
69 }
70
71 void print(int r){
72 while(q[r].pre){
73 int l=q[r].pre;
74 if(q[r].x==q[l].x){
75 if(q[r].y>q[l].y)
76 ans[++tot]='E';
77 else ans[++tot]='W';
78 }else{
79 if(q[r].x<q[l].x)
80 ans[++tot]='N';
81 else ans[++tot]='S';
82 }r=l;
83 }
84 for(int i=tot;i>=1;i--){
85 printf("%c
",ans[i]);
86 }
87 }
88
89 void bfs(int ssx,int ssy){
90 q[1]=(node){ssx,ssy,0};
91 int l=0,r=0;r++;
92 while(l<r){
93 l++;
94 node u=q[l];
95 map[u.x][u.y]=1;
96 if(u.x==fx&&u.y==fy){
97 print(l);return;
98 }
99 for(int i=0;i<=3;i++){
100 int nx=u.x+dx[i];
101 int ny=u.y+dy[i];
102 if(!check(nx,ny))continue;
103 if(map[nx][ny]==0){
104 map[nx][ny]=1;
105 r++;q[r]=(node){nx,ny,l};
106 if(nx==fx&&ny==fy){
107 print(r);return;
108 }
109 }
110 }
111 }
112 puts("-1");
113 }
114
115 int main(){
116 fre();
117 init();
118 if(map[sx][sy]==1){puts("-1");return 0;}
119 bfs(sx,sy);
120 }
我的代码有些步骤可能是多余的,因为之前我显示的是超时,所以我把所有可能降低一丢时间复杂度的地方都魔改了,所以不要在意细节了