版权声明:本文为博主原创作品, 转载请注明出处! https://blog.csdn.net/solider98/article/details/84306813
思路分析: 考虑使用BFS, 计算左上角结点至通过对角线(可旋转)到达的各个结点的最短距离, 如果两个对角结点A, B之间无连线, 那么欲使A, B相连, 需要旋转A, B对应区域的对角线. 此时设A, B之间距离为1, 如果A, B之间有连线那么距离为0, 为了实现更佳有效的剪枝, 考虑每次从对头取出元素进行扩展时, 将需要加入队列的到起点距离较大的结点放在队尾, 到起点距离较小的结点放在队头, 具体实现如下AC代码所示:
//CH2601_电路维修
#include <iostream>
#include <deque>
#include <cstdio>
#include <algorithm>
#include <cstring>
#define mp make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 505;
char G[MAX][MAX]; int R, C, d[MAX][MAX];
int main(){
int T; scanf("%d", &T);
while(T--){
scanf("%d %d", &R, &C);
for(int i = 1; i <= R; ++i) scanf("%s", G[i] + 1);
memset(d, 0x3f, sizeof(d));
deque<pair<int, int> > dq; dq.push_back(mp(0, 0)), d[0][0] = 0;
while(!dq.empty()){
int x = dq.front().fi, y = dq.front().se; dq.pop_front();
//考察左上结点
if(x - 1 >= 0 && y - 1 >= 0){
int len = G[x][y] == '\\'? 0: 1, t = d[x][y] + len, &k = d[x - 1][y - 1];
if(t < k) {
k = t; if(len) dq.push_back(mp(x - 1, y - 1)); else dq.push_front(mp(x - 1, y - 1));
}
}
//考察右上结点
if(x - 1 >= 0 && y + 1 <= C){
int len = G[x][y + 1] == '/'? 0: 1, t = d[x][y] + len, &k = d[x - 1][y + 1];
if(t < k){
k = t; if(len) dq.push_back(mp(x - 1, y + 1)); else dq.push_front(mp(x - 1, y + 1));
}
}
//考察左下结点
if(x + 1 <= R && y - 1 >= 0){
int len = G[x + 1][y] == '/'? 0: 1, t = d[x][y] + len, &k = d[x + 1][y - 1];
if(t < k){
k = t; if(len) dq.push_back(mp(x + 1, y - 1)); else dq.push_front(mp(x + 1, y - 1));
}
}
//考察右下结点
if(x + 1 <= R && y + 1 <= C){
int len = G[x + 1][y + 1] == '\\'? 0: 1, t = d[x][y] + len, &k = d[x + 1][y + 1];
if(t < k) {
k = t; if(len) dq.push_back(mp(x + 1, y + 1)); else dq.push_front(mp(x + 1, y + 1));
}
}
}
if(d[R][C] == 0x3f3f3f3f) printf("NO SOLUTION\n"); else printf("%d\n", d[R][C]);
}
return 0;
}