Description
给出一张地图,这张地图被分为 n×m(n,m<=100)个方块,任何一个方块不是平地就是高山。平地可以通过,高山则不能。现在你处在地图的(x1,y1)这块平地,问:你至少需要拐几个弯才能到达目的地(x2,y2)?你只能沿着水平和垂直方向的平地上行进,拐弯次数就等于行进方向的改变(从水平到垂直或从垂直到水平)的次数。例如:如图 1,最少的拐弯次数为5。
Input
第 1行:n m 第 2至n+1行:整个地图地形描述(0:空地;1:高山), 如图,第2行地形描述为:1 0 0 0 0 1 0 第3行地形描述为:0 0 1 0 1 0 0 …… 第n+2行:x1 y1 x2 y2 (分别为起点、终点坐标)
Output
s (即最少的拐弯次数
Sample Input
5 7
1 0 0 0 0 1 0
0 0 1 0 1 0 0
0 0 0 0 1 0 1
0 1 1 0 0 0 0
0 0 0 0 1 1 0
1 3 1 7
Sample Output
5
解题思路
广搜
只比板子多了记录转弯
可以把方向数组的“上下左右”巧妙地改变一下顺序,按水平顺序“上左下右”,i%2==0是一个水平情况,i%2!=0是一个水平情况,发现扩展的点和当前点不是一个情况,转弯次数加1
#include<iostream>
#include<cstdio>
using namespace std;
const int way[4][2]={{-1,0},{0,-1},{1,0},{0,1}};//上,左,下,右
int a[150][150],n,m,s[150][150][2],sx,sy,ex,ey;
int v[100100][2],h,t=1;
bool check(int x,int y){
return (x>0&&x<=n&&y>0&&y<=m);
}
void BFS(int x,int y){
s[x][y][0]=1;//s[][][0]记录转弯次数
s[x][y][1]=-1;//s[][][1]记录水平情况,第一个点特殊标记
a[x][y]=1;
v[t][0]=x,v[t][1]=y;
while(h++<t){
x=v[h][0],y=v[h][1];
for(int i=0;i<4;i++){
int xx=x+way[i][0];
int yy=y+way[i][1];
if(check(xx,yy)&&!s[xx][yy][0]&&!a[xx][yy]){
v[++t][0]=xx,v[t][1]=yy;
if(s[x][y][1]==-1)s[xx][yy][0]=s[x][y][0];//特判是不是第一个点过来的
else
if(i%2!=s[x][y][1])s[xx][yy][0]=s[x][y][0]+1;//如果不是一个水平情况,转弯数+1
else s[xx][yy][0]=s[x][y][0];
s[xx][yy][1]=i%2;
a[xx][yy]=1;
if(xx==ex&&yy==ey)return;
}
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
BFS(sx,sy);
printf("%d",s[ex][ey][0]-1);
}