双端队列BFS
175. 电路维修
电路板的整体结构是一个 R 行 C 列的网格(R,C≤500),如下图所示。

她准备通过计算,旋转最少数量的元件,使电源与发动装置通过若干条短缆相连。
注意:只能走斜向的线段,水平和竖直线段不能走。
输入格式
输入文件包含多组测试数据。
第一行包含一个整数 T,表示测试数据的数目。
对于每组测试数据,第一行包含正整数 R 和 C,表示电路板的行数和列数。
之后 R 行,每行 C 个字符,字符是"/"和"\"中的一个,表示标准件的方向。
输出格式
对于每组测试数据,在单独的一行输出一个正整数,表示所需的最小旋转次数。
如果无论怎样都不能使得电源和发动机之间连通,输出 NO SOLUTION。
数据范围
1 ≤ R , C ≤ 500
1 ≤ T ≤ 5
输入样例:
1
3 5
\\/\\
\\///
/\\\\
输出样例:
1
思路:
这是个有权值的搜索路径问题,该路线权值由该点是否需要改变决定。
这里使用双端队列deque,将权值为0的放队首,权值为1的放队尾。
--日后再更
代码:
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
typedef pair<int ,int> PII;
const int N = 505, M = 505 * 505;
int T, n, m;
char g[N][N];
int dist[N][N];
bool book[N][N];
int NEXT[4][2] = {{-1,1},{1,1},{1,-1},{-1,-1}};
int aa[4][2] = {{-1,0},{0,0},{0,-1},{-1,-1}};
int bfs(){
deque<PII> q;
memset(book,0,sizeof book);
memset(dist,0x3f,sizeof dist);
q.push_back({0, 0});
dist[0][0] = 0;
//cout << q.size() << endl;
while(q.size()){
PII t = q.front();
q.pop_front();
int x = t.x, y = t.y;
if(x == n && y == m){
return dist[x][y];
}
if(book[x][y])continue;
book[x][y] = true;
char s[10] = "/\\/\\";
for(int i = 0; i < 4; i++){
int a = x + NEXT[i][0];
int b = y + NEXT[i][1];
if(a < 0 || b < 0 || a > n || b > m)continue;
if(book[a][b])continue;
int ga = x + aa[i][0], gb = y + aa[i][1];
int w = (g[ga][gb] != s[i]);
int DIST = dist[x][y] + w;
if(DIST < dist[a][b]) dist[a][b] = DIST;
//dist[a][b] = dist[x][y] + w;
//printf("w = %d %d %d dist = %d x = %d y = %d ga = %d gb = %d\n",w,a,b,dist[a][b],x,y,ga,gb);
if(w == 0) q.push_front({a,b});
else q.push_back({a,b});
}
}
return -1;
}
int main(){
cin >> T;
while(T--){
cin >> n >> m;
for(int i = 0; i < n; i++)scanf("%s",g[i]);
if((n + m) & 1) printf("NO SOLUTION\n");
else printf("%d\n",bfs());
}
return 0;
}

浙公网安备 33010602011771号