电路维修
题目链接:ybt高效进阶1-5-5
题目大意
就是有一块图分成很多个方格,路放在每个放着中的某一条对角线中,然后要你连通左上角和右下角。
问你最少要改变多少个方格对角线的位置,如果无法连通,则输出 NO SOLUTION
。
思路
因为电线的交点都在方格的四角,那我们就考虑以方格的四角作为每个点,就一共有
(
N
+
1
)
×
(
M
+
1
)
(N+1)\times(M+1)
(N+1)×(M+1) 个点,然后跑 bfs。
四个方向,判断一下这个点走这个方向是否要改变电线的位置,从而看距离是否加一。
不会出现一个电线转两次的情况,因为如果这样一定会有更优的。
然后如果无法跑到终点,就是无法连通。
主要就是注意一下,我点是从 0 0 0 开始,电线是从 1 1 1 开始,那算四个方向的时候向下向右的都是加一,而向下想做的就是算点的要减一,而算电线的就不用减。
代码
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
struct xx {
int dis, x, y;
}now;
bool a[501][501];
int n, m, T, ans, in[501][501];
queue <xx> q;
char c;
bool ch(int x, int y) {
if (x < 0 || x > n) return 0;
if (y < 0 || y > m) return 0;
return 1;
}
bool bfs() {
while (!q.empty()) q.pop();
q.push((xx){0, 0, 0});
in[0][0] = 0;
while (!q.empty()) {
now = q.front();
q.pop();
if (now.dis >= ans) continue;
if (now.x == n && now.y == m) {
ans = now.dis;
continue;
}
//右下
if (ch(now.x + 1, now.y + 1) && (in[now.x + 1][now.y + 1] == -1 || in[now.x + 1][now.y + 1] > (now.dis + (a[now.x + 1][now.y + 1] != 1)))) {
in[now.x + 1][now.y + 1] = now.dis + (a[now.x + 1][now.y + 1] != 1);
q.push((xx){now.dis + (a[now.x + 1][now.y + 1] != 1), now.x + 1, now.y + 1});
}
//右上
if (ch(now.x - 1, now.y + 1) && (in[now.x - 1][now.y + 1] == -1 || in[now.x - 1][now.y + 1] > (now.dis + (a[now.x][now.y + 1] != 0)))) {
in[now.x - 1][now.y + 1] = now.dis + (a[now.x][now.y + 1] != 0);
q.push((xx){now.dis + (a[now.x][now.y + 1] != 0), now.x - 1, now.y + 1});
}
//左下
if (ch(now.x + 1, now.y - 1) && (in[now.x + 1][now.y - 1] == -1 || in[now.x + 1][now.y - 1] > (now.dis + (a[now.x + 1][now.y] != 0)))) {
in[now.x + 1][now.y - 1] = now.dis + (a[now.x + 1][now.y] != 0);
q.push((xx){now.dis + (a[now.x + 1][now.y] != 0), now.x + 1, now.y - 1});
}
//左上
if (ch(now.x - 1, now.y - 1) && (in[now.x - 1][now.y - 1] == -1 || in[now.x - 1][now.y - 1] > (now.dis + (a[now.x][now.y] != 1)))) {
in[now.x - 1][now.y - 1] = now.dis + (a[now.x][now.y] != 1);
q.push((xx){now.dis + (a[now.x][now.y] != 1), now.x - 1, now.y - 1});
}
}
if (ans == 2147483647) return 0;
return 1;
}
int main() {
scanf("%d", &T);
for (int times = 1; times <= T; times++) {
ans = 2147483647;
memset(in, -1, sizeof(in));
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) {
c = getchar();
while (c != '/' && c != '\\') c = getchar();
if (c == '/') a[i][j] = 0;
else a[i][j] = 1;
}
if (!bfs()) printf("NO SOLUTION\n");
else printf("%d\n", ans);
}
return 0;
}