每个方格的四个角看成是节点 如果节点与节点之间有斜线链接
就把两个节点间的权值设为0 否则设为1 (看成是需要转一次) 这样
就得到一张边权为1或0的无向图 使用bfs+deque 在每个节点上沿
分支扩展时 如果时权值为0的边从队头入队 如果是权值为1的边从
队尾入队
#include<bits/stdc++.h>
using namespace std;
typedef pair< int, int > PII;
const int N = 510;
char g[N][N];
int n, m;
int dist[N][N];
int dx[4] = {-1, 1, 1, -1};
int dy[4] = {-1, -1, 1, 1}; //dx dy 是节点往左上 右上 左下 右下 的坐标偏移量
int ix[4] = {-1, 0, 0, -1}; //ix iy 是节点的左上 上 左 节点本身坐标 代表方格中电线的摆放位置
int iy[4] = {-1, -1, 0, 0};
char str[] = "\\/\\/";
bool st[N][N];
int bfs()
{
memset( dist, 0x3f, sizeof dist );
dist[0][0] = 0;
deque< PII > q;
q.push_front( {0, 0} );
while( q.size() )
{
PII t = q.front();
q.pop_front();
int x = t.first, y = t.second;
if( st[x][y] )
continue;
st[x][y] = true;
for( int i = 0; i < 4; i ++ )
{
int a = x + dx[i], b = y + dy[i];
int j = x + ix[i], k = y + iy[i];
if( a >= 0 && a <= n && b >= 0 && b <= m )
{
int w = 0;
if( g[j][k] != str[i] )
w = 1;
if( dist[a][b] > dist[x][y] + w )
{
dist[a][b] = dist[x][y] + w;
if( w )
q.push_back( {a, b} );
else
q.push_front( {a, b} );
}
}
}
}
if( dist[n][m] == 0x3f3f3f3f )
return -1;
else
return dist[n][m];
}
int main()
{
int T;
cin >> T;
while( T -- )
{
memset( st, 0, sizeof st );
cin >> n >> m;
for( int i = 0; i < n; i ++ )
cin >> g[i];
int t = bfs();
if( t == -1 )
cout << "NO SOLUTION" << endl;
else
cout << t << endl;
}
}