思路:首先要明确一点,只有在边权要么是0要么是1的图上才能使用双端队列bfs。
在题目的这个模型里面,要把每一个交叉点看做一个节点,起点就是(0,0),终点就是(n,m),与普通的二维迷宫图不同,这里扩展的方向不是普通的上下左右,而是左上,左下,右上,右下,而判断距离是0,还是1就要根据两点之间的斜线的形状是否是刚好连着两个点,是的话就是0,否则的话就是1,因为要靠旋转一次来达成连接的目的,对于输入的字符串图另外用一个图去存储,
如下图所示:每个格子里面就是斜线的编号,如果要判断节点(0,0)和节点(1,1)是否相连,就要看他们之间的(0,0)处的斜线是不是 \ 的形状,是的话(0,0)到(1,1)的距离为0,否则的话距离为1.
代码:
#include<iostream>
#include<cstring>
#include<algorithm>
#include<deque>
#define x first
#define y second
using namespace std;
typedef pair<int,int >PII;
const int N=510,M=N*N;
int dist[N][N];
char g[N][N];
bool st[N][N];
int n,m;
int bfs()
{
memset(dist,0x3f,sizeof dist);
memset(st,0,sizeof st);
dist[0][0]=0;
deque<PII>q;
q.push_back({0,0});
char cs[]="\\/\\/";//此处'\\'表示成一个‘\’
int dx[4]={-1,-1,1,1};
int dy[4]={-1,1,1,-1};
int ix[4]={-1,-1,0,0};
int iy[4]={-1,0,0,-1};
while(q.size())
{
PII t=q.front();
q.pop_front();
if(st[t.first][t.second]) continue;
st[t.first][t.second]=true;
for(int i=0;i<4;i++)
{
int a=t.first+dx[i];
int b=t.second+dy[i];
if(a<0||a>n||b<0||b>m) continue;
int ca=t.first+ix[i];
int cb=t.second+iy[i];
int d=dist[t.first][t.second]+(g[ca][cb]!=cs[i]);
if(d<dist[a][b])
{
dist[a][b]=d;
if(g[ca][cb]!=cs[i]) q.push_back({a,b});
else q.push_front({a,b});
}
}
}
return dist[n][m];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%s",g[i]);
int p=bfs();
if(p==0x3f3f3f3f) puts("NO SOLUTION");
else printf("%d\n",p);
}
return 0;
}