【YbtOJ高效进阶 广搜-5】电路维修

链接

YbtOJ高效进阶 广搜-5

题目描述

在这里插入图片描述

样例输入

1
3 5
\\/\\
\\///
/\\\\

样例输出

1

思路

傻逼题,每个格子视作一个节点,然后相邻的格子就连边,然后再考虑要不要转向,如果要就把边权设为1,否则为0,然后求最短路就可以了
要用双端队列

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<deque>

using namespace std;

char c;
int n, m, t, T;
int vis[1000500], Ans[1000500], h[1000500];

struct lL
{
    
    
	int to, next, val;
}L[1000500];

char read() {
    
    
    char cc = getchar();
    while (cc != '/' && cc != '\\') cc = getchar();
    return cc;
}//读入处理(YbtOJ传统艺能)

void Connect(int x, int y, int xx, int yy, int val)
{
    
    
	int num1 = (x - 1) * (m + 1) + y;
	int num2 = (xx - 1) * (m + 1) + yy;
	L[++t] = (lL){
    
    num2, h[num1], val};
	h[num1] = t;
	L[++t] = (lL){
    
    num1, h[num2], val};
	h[num2] = t;
}//连边

void BFS()
{
    
    
	deque<int>Q;
	Q.push_back(1);
	vis[1] = 1;
	while(Q.size())
	{
    
    
		int tot = Q.front();
		vis[tot] = 1;
		Q.pop_front();
		for(int i = h[tot]; i; i = L[i].next)
		{
    
    
			int to = L[i].to;
			if(L[i].val + Ans[tot] < Ans[to])
			{
    
    
				Ans[to] = Ans[tot] + L[i].val;
				if(!vis[to]) {
    
    
					if(L[i].val == 0) Q.push_front(to);
						else Q.push_back(to);
				}
			}//最短路
		}
	}
}

int main()
{
    
    
	scanf("%d", &T);
	while(T--)
	{
    
    
		memset(Ans, 0x7f, sizeof(Ans));
		memset(vis, 0, sizeof(vis));
		memset(L, 0, sizeof(L));
		memset(h, 0, sizeof(h));
		scanf("%d%d", &n, &m); t = 0;
		for(int i = 1; i <= n; ++i)
		for(int j = 1; j <= m; ++j)
		{
    
    
			c = read();
			if(c == '/') {
    
    
				Connect(i, j, i + 1, j + 1, 1);
				Connect(i + 1, j, i, j + 1, 0);
			}
			else {
    
    
				Connect(i, j, i + 1, j + 1, 0);
				Connect(i + 1, j, i, j + 1, 1);
			}
		} 
		Ans[1] = 0;
		BFS();
		if(Ans[(n + 1) * (m + 1)] < 1e6)
			printf("%d\n", Ans[(n + 1) * (m + 1)]);
		else printf("NO SOLUTION\n");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/LTH060226/article/details/113003538