这道题作为一道广度优先搜索的题目,和其他的写法没有太大不同,但是有很多坑~,(多踩几次就填上了)
1.在这道题中,哈利可以只要与奖杯在题目所描述的八个方向上能够直接通往奖杯(也就是说不能有墙),那么就可以结束搜索,次数也可以不用加一。
2.这道题要重复输入多遍哈利和奖杯的坐标,而且是先输入奖杯,在输入哈利坐标(坑!),所以可以使用一个数组先记录下来,然后每一遍都进行初始化
3.再就是奖杯一开始就在哈利的手中(奖杯坐标与哈利坐标重合),需要特判
4.这道题不能只用一个数组来记录不能走到的点,因为如果在搜索的过程中只用一个数组进行记录,就会导致走过的点和本身是墙的点都变成一个不能走的点,但是在最后判断能否直接拿到的时候并不能考虑走过的点,所以需要用两个数组进行记录,一个记录墙壁,一个记录已走过的点,避免混乱
源代码:
#include<iostream> #include<cstdio> #include<math.h> #include<algorithm> #include<cstring> #include<queue> using namespace std; struct STU { int xx; int yy; }; queue<STU> q; int go[5][2]={{0,0},{1,0},{-1,0},{0,1},{0,-1}}; int val[1600][1600]; int mapp1[1600][1600];//记录墙壁坐标 int mapp2[1600][1600];//记录已走点坐标 int step[1600][1600]; int flag,n,m,ex,ey,bx,by,tx,ty,qx,qy,ans; char a; int win(int x,int y)//判断可不可以用“飞来咒”直接拿到奖杯 { if(x==ex&&y==ey)//奖杯和哈利重合 { return 1; } if(x==ex)//在同一水平直线上 { for(int i=min(y,ey);i<=max(y,ey);i++) { if(mapp1[x][i]==1) return 0; } return 1; } if(y==ey)//在同一竖直直线上 { for(int i=min(x,ex);i<=max(x,ex);i++) { if(mapp1[i][y]==1) return 0; } return 1; } if(x-y==ex-ey)//在同一方向为东北——西南的直线上 { for(int i=1;i<=abs(ex-x);i++) { if(x<ex) { if(mapp1[x+i][y+i]==1) return 0; } else { if(mapp1[x-i][y-i]==1) return 0; } } return 1; } if(x+y==ex+ey)//在同一方向为西北——东南的直线上 { for(int i=1;i<=abs(x-ex);i++) { if(x<ex) { if(mapp1[x+i][y-i]==1) return 0; } else { if(mapp1[x-i][y+i]==1) return 0; } } return 1; } return 0;//啥都不符合。。。 } int bfs(int x,int y)//正常广度优先搜索 { q.push((STU){x,y}); mapp2[x][y]=1; step[x][y]=0; while(q.size()!=0) { qx=q.front().xx; qy=q.front().yy; q.pop(); if(win(qx,qy)==1)//能拿到就结束 { return step[qx][qy]; } for(int i=1;i<=4;i++) { tx=qx+go[i][0]; ty=qy+go[i][1]; if(tx<1||ty<1||tx>n||ty>m||mapp2[tx][ty]==1) { continue; } mapp2[tx][ty]=1; step[tx][ty]=step[qx][qy]+1; q.push((STU){tx,ty}); } } return -1;//拿不到打个标记 } int main(void) { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { cin>>a; if(a=='X') val[i][j]=1;//标记墙壁,之后每一遍输入均可使用 } } for( ; ; ) { scanf("%d%d%d%d",&ex,&ey,&bx,&by); if(bx==0&&by==0&&ex==0&&ey==0) { break; } for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { mapp2[i][j]=mapp1[i][j]=val[i][j];//走过的也把墙壁标记为已走路径,不再经过 } } ans=bfs(bx,by); if(ans==-1) { printf("Poor Harry "); } else { printf("%d ",ans); } memset(step,0,sizeof(step));//切记初始化 memset(mapp1,0,sizeof(mapp1)); memset(mapp2,0,sizeof(mapp2)); while(q.size()!=0)//队列初始化 { q.pop(); } } return 0; }