HDU 1728 逃离迷宫【BFS】
题意:给出一个起点,一个终点,规定的转弯次数,问能否在规定的转弯次数内到达终点---
这一题是学(看)习(题)的(解)@_@
主要学了两个地方
一个是剪枝,如果搜到的当前点的转弯次数小于该点turn数组记录下来的转弯次数,才有必要将它加入队列。
另一个是记录转弯方向 在结构体里面定义一个turn来记录转弯的个数,用dir来记录当前所在的方向(因为搜的时候是四个方向dir[4][2]来搜的,直接用i确定当前方向即可)
想想自己第一次做的时候的doubi想法,用dfs做,然后dfs(x,y,px,py),再判断由(x+dir[i][0],y+dir[i][1])与(x,y)构成的直线斜率和(x,y)和(px,py)构成的斜率乘积是否为-1-----果断没有写对----
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 using namespace std; 7 int turn[105][105]; 8 int n,m,k; 9 int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; 10 char map[105][105]; 11 struct node 12 { 13 int x,y; 14 int turn,dir;//用turn来记录转弯的个数,用dir来记录当前的方向 15 } st,en,now,next; 16 queue<node>q; 17 void bfs() 18 { 19 while(!q.empty()) q.pop(); 20 now.x=st.x;now.y=st.y;now.dir=-5;now.turn=0;//初始的方向可以定义为任意一个后来不会出现的方向 21 turn[now.x][now.y]=0; //在起点时可以转向任意方向,令为0 22 q.push(now); 23 while(!q.empty()) 24 { 25 now=q.front();q.pop(); 26 27 for(int i=0;i<4;i++) 28 { 29 next.x=now.x+dir[i][0]; 30 next.y=now.y+dir[i][1]; 31 next.dir=now.dir; 32 next.turn=now.turn; 33 if(now.x==en.x&&now.y==en.y&&now.turn<=k) 34 { 35 printf("yes\n"); 36 return; 37 } 38 if(next.x<1||next.x>m||next.y<1||next.y>n||map[next.x][next.y]=='*') continue;//第一次剪枝 39 if(next.dir!=i&&next.dir!=-5) //如果当前方向和起始不同,则turn++ 40 next.turn++; 41 if(next.turn>k) continue;//第二次剪 枝,转弯次数超过了,则剪枝 42 if(next.x==en.x&&next.y==en.y&&next.turn<=k) 43 { 44 printf("yes\n"); 45 return; 46 } 47 48 if(next.turn<=turn[next.x][next.y])//第三次剪枝,如果当前转弯的个数小于当前点的转弯个数,才有继续搜索的必要 49 { 50 next.dir=i; 51 turn[next.x][next.y]=next.turn; 52 q.push(next); 53 } 54 } 55 } 56 printf("no\n"); 57 return; 58 } 59 int main() 60 { 61 int ncase,i,j; 62 scanf("%d",&ncase); 63 while(ncase--) 64 { 65 scanf("%d %d",&m,&n); 66 for(i=1;i<=m;i++) 67 for(j=1;j<=n;j++) 68 { 69 cin>>map[i][j]; 70 turn[i][j]=1000000;//初始化 每一点的转弯个数为一个极大的值 71 } 72 cin>>k>>st.y>>st.x>>en.y>>en.x; 73 bfs(); 74 } 75 }