【ybt高效进阶1-5-5】电路维修

电路维修

题目链接: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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值