HDU-1728-逃离迷宫
题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1728
程序分析:
题目是要让你计算在一个迷宫里从一个点到另一个点要转的弯数是否小于给定的弯数限定。也就是判断能否在有限弯数内从一个点到达另一点。只能从四个方向走。输入数据有点与以往不同,注意输入的行跟列还有两个点的做坐标。
解决方法:
迷宫之类的题大多数都能使用BFS或者DFS吧,不过这道题比较多陷阱和技巧,首先,每一种走法经过的弯可能是不同的,虽然都是经过同一个点,但是到达这个点时经过的弯路可能就不同了。应该有点DP的味道吧,BFS+DP可以算出来。这需要开多一个二维数组来保存这个点最小的转弯数,到达终点后判断这个点的转弯数是否小于或等于给予的限定就可以了。这应该是属于UCS查找吧,是BFS的升级版,就是加了个进队列的条件。
还可以用另一种方法做, 一张图里面的两个点a,b, 如要从a到b,那么我们可以一行一列得判断b点是否跟a用行或用列,也必须是这一行或一列ab之间无障碍,那就可以是之间到达b而无需转弯了,如果是遇到障碍,那就必须转弯,如果是在ab之间移动,就一直进队列出队列直到到达b点,每一次循四个方向时最多的是弯数加一,要么不加(起点)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<queue> 3 using namespace std; 4 5 const int INF = 1<<30; 6 const int Max = 105; 7 char used[Max][Max]; 8 bool flag[Max][Max]; 9 int n, m, k; 10 int to[4][2]={-1,0, 1,0, 0,-1, 0,1}; // {0,1}, {1,0},{0,-1}, {-1,0}}; 11 12 //up down left right 13 typedef struct Node 14 { 15 int x, y, s; 16 }Node; 17 18 int BFS(int x, int y, int x1, int y1) 19 { 20 memset(flag, false, sizeof(flag)); 21 queue<Node>Q; 22 Node s; 23 s.x = x; 24 s.y = y; 25 s.s = -1; 26 flag[x][y] = true; 27 Q.push(s); 28 while(!Q.empty()) 29 { 30 Node go, st; 31 go = Q.front(); 32 Q.pop(); 33 if(go.x==x1 && go.y==y1 && go.s<=k) 34 return 1; 35 for(int i=0; i<4; i++) 36 { 37 st.x = go.x+to[i][0]; 38 st.y = go.y+to[i][1]; 39 st.s = go.s+1; 40 if(st.s>k) 41 continue; 42 while(st.x>=0 && st.x<m && st.y>=0 && st.y<n && used[st.x][st.y]=='.') 43 { 44 if(!flag[st.x][st.y]) 45 { 46 flag[st.x][st.y] = true; 47 Q.push(st); 48 } 49 st.x = st.x + to[i][0]; 50 st.y = st.y + to[i][1]; 51 if(st.x == x1 && st.y == y1 && st.s <= k) 52 return 1; 53 } 54 } 55 } 56 return 0; 57 } 58 59 60 61 int main() 62 { 63 int t; 64 int x1, x2, y1, y2; 65 cin>>t; 66 while(t--) 67 { 68 cin>>m>>n; //行列 69 for(int i=0; i<m; i++) 70 { 71 scanf("%s", used[i]); 72 } 73 cin>>k>>y1>>x1>>y2>>x2; //输入出口位置的坐标(列,行) 74 if(x1==x2 && y1==y2) 75 { 76 cout<<"yes"<<endl; 77 continue; 78 } 79 if(BFS(x1-1, y1-1, x2-1, y2-1) == 1) 80 cout<<"yes"<<endl; 81 else 82 cout<<"no"<<endl; 83 } 84 return 0; 85 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<queue> 3 #include<string> 4 using namespace std; 5 const int INF = 100000; 6 const int Max = 105; 7 char used[Max][Max]; 8 int Min[Max][Max]; 9 int n, m, k; 10 int to[4][2]={-1,0, 1,0, 0,-1, 0,1}; 11 //up down left right 12 typedef struct Node 13 { 14 int x, y; 15 int sum; 16 int s; 17 }Node; 18 19 int BFS(int x, int y, int x1, int y1) 20 { 21 for(int i=0; i<=m; i++) 22 for(int j=0; j<=n; j++) 23 Min[i][j] = INF; 24 queue<Node>Q; 25 Node go,st; 26 go.x = x; 27 go.y = y; 28 go.s = -1; 29 go.sum = 0; 30 Min[x][y] = 0; 31 Q.push(go); 32 while(!Q.empty()) 33 { 34 st = Q.front(); 35 Q.pop(); 36 if(st.x==x1 && st.y==y1) 37 return st.sum; 38 for(int i=0; i<4; i++) 39 { 40 go = st; 41 go.x += to[i][0]; 42 go.y += to[i][1]; //上 43 if(go.x>=0 && go.x<m && go.y>=0 && go.y<n && used[go.x][go.y]=='.') 44 { 45 if(go.s!=i && go.s!=-1) 46 { 47 go.sum=st.sum+1; 48 } 49 go.s=i; 50 if(go.sum <= k && go.sum <= Min[go.x][go.y]) 51 { 52 Min[go.x][go.y] = go.sum; 53 Q.push(go); 54 } 55 } 56 } 57 } 58 return Min[x1][y1]; 59 } 60 int main() 61 { 62 int x1, x2, y1, y2; 63 int t; 64 cin>>t; 65 while(t--) 66 { 67 cin>>m>>n; //行列 68 for(int i=0; i<m; i++) 69 { 70 scanf("%s", used[i]); 71 } 72 cin>>k>>y1>>x1>>y2>>x2; //输入出口位置的坐标(列,行) 73 if(x1==x2 && y1==y2) 74 { 75 cout<<"yes"<<endl; 76 continue; 77 } 78 if(BFS(x1-1, y1-1, x2-1, y2-1) <= k) 79 cout<<"yes"<<endl; 80 else 81 cout<<"no"<<endl; 82 } 83 return 0; 84 }