[CH2601] 电路维修 题解

描述

Ha'nyu是来自异世界的魔女,她在漫无目的地四处漂流的时候,遇到了善良的少女Rika,从而被收留在地球上。Rika的家里有一辆飞行车。有一天飞行车的电路板突然出现了故障,导致无法启动。
电路板的整体结构是一个R行C列的网格(R,C≤500),如右图所示。每个格点都是电线的接点,每个格子都包含一个电子元件。电子元件的主要部分是一个可旋转的、连接一条对角线上的两个接点的短电缆。在旋转之后,它就可以连接另一条对角线的两个接点。电路板左上角的接点接入直流电源,右下角的接点接入飞行车的发动装置。

Ha'nyu发现因为某些元件的方向不小心发生了改变,电路板可能处于断路的状态。她准备通过计算,旋转最少数量的元件,使电源与发动装置通过若干条短缆相连。不过,电路的规模实在是太大了,Ha'nyu并不擅长编程,希望你能够帮她解决这个问题。

输入格式

输入文件包含多组测试数据。第一行包含一个整数T 表示测试数据的数目。
对于每组测试数据,第一行包含正整数R 和C,表示电路板的行数和列数。
之后R 行,每行C 个字符,字符是"/"和""中的一个,表示标准件的方向。

输出格式

对于每组测试数据,在单独的一行输出一个正整数,表示所需的缩小旋转次数。
如果无论怎样都不能使得电源和发动机之间连通,输出NO SOLUTION。

样例输入

1
3 5
/
///
/\
样例输出

1
数据范围与约定

对于40% 的数据,R,C≤5。
对于100% 的数据,R,C≤500,T≤5。
样例解释

样例的输入对应于题目描述中的情况。
只需要按照下面的方式旋转标准件,就可以使得电源和发动机之间连通。

来源

杜宇飞,石家庄二中【Nescafé 5】杯NOIP模拟赛


思路:考虑BFS,从左上角开始搜索,显然当边长一奇一偶时无法走到右下角,且左上 右下角一定为''.则可以按照每个格子保存的斜线方向往当前格子的四周bfs,判断是否需要改变.用介质为当前旋转次数的优先队列维护BFS即可
代码

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define rg register
#define LL long long
#define __space putchar(' ')
#define __endl putchar('
')
template <typename qwq> inline void read(qwq & x)
{
    x = 0;
    rg int f = 1;
    rg char c = getchar();
    while (c < '0' || c > '9')
    {
        if (c == '-') f = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9')
    {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    x *= f;
}
template <typename qaq> inline void print(qaq x)
{
    if (x < 0)
    {
        putchar('-');
        x = -x;
    }
    if (x > 9) print(x / 10);
    putchar(x % 10 + '0');
}
char Map[2333][2333];
int n,m,t;
int ans[2333][2333];
int dx[] = {0,0,1,1,0,-1,-1,-1,1};
int dy[] = {0,1,0,1,-1,0,-1,1,-1};
//1:右 2:下 3:右下 4:左 5:上 6:左上 7:右上 8:左下 
struct node
{
	int w,x,y;
	char c;
	friend bool operator < (const node a,const node b)
	{
		return a.w > b.w;
	}
}start;
priority_queue<node>heap;
//first:cost second:point 
inline void prework()
{
	while(!heap.empty()) heap.pop();
	for (rg int i = 1;i <= n;++i)
	{
		for (rg int j = 1;j <= m;++j)
		{
			ans[i][j] = 0x7f7f7f7f;
		}
	}
	ans[1][1] = 0;
}
#define you 1
#define xia 2
#define youxia 3
#define zuo 4
#define shang 5
#define zuoshang 6
#define youshang 7
#define zuoxia 8
inline void boy_friend_search()
{
	heap.push(start);
	while (!heap.empty())
	{
		rg node now = heap.top();
		rg int x = now.x,y = now.y;
		rg char c = now.c;
		heap.pop();
		for (rg int i = 1;i <= 8;++i)
		{
			rg int nx = x + dx[i],ny = y + dy[i];
			rg char nc;
			if (nx < 1 || nx > n || ny < 1 || ny > m) continue;
			if (i == zuo || i == you || i == shang || i == xia)// 向左/右/上/下走 
			{
				if (c == Map[nx][ny])//如果两个相同的话 
				{
					//若要保证联通则必须更改 
					if (ans[x][y] + 1 < ans[nx][ny])
					{
						ans[nx][ny] = ans[x][y] + 1;
//						nc = (Map[x][y] == '/') ? 92 : '/';
						if (c == '/') nc = 92;
						else nc = '/';
						if (nx == n && ny == m) return;
						heap.push((node) {ans[nx][ny],nx,ny,nc});
					}
				}
				else
				{
					//否则不需要更改 
					if (ans[x][y] < ans[nx][ny])
					{
						ans[nx][ny] = ans[x][y];
						if (nx == n && ny == m) return;
						heap.push((node) {ans[nx][ny],nx,ny,Map[nx][ny]});
					}
				}
			}
			else if (i == zuoshang || i == youxia)//向 左上/右下 
			{
				if (c == '/') continue;
				if (c != Map[nx][ny])//如果两个不同的话 
				{
					//若要保证联通则必须更改 
					if (ans[x][y] + 1 < ans[nx][ny])
					{
						ans[nx][ny] = ans[x][y] + 1;
						nc = c;
						if (nx == n && ny == m) return;
						heap.push((node) {ans[nx][ny],nx,ny,nc});
					}
				}
				else
				{
					//否则不需要更改 
					if (ans[x][y] < ans[nx][ny])
					{
						ans[nx][ny] = ans[x][y];
						if (nx == n && ny == m) return;
						heap.push((node) {ans[nx][ny],nx,ny,Map[nx][ny]});
					}
				}
			}
			else// 左下/右上 
			{
				if (c == 92) continue;
				if (c != Map[nx][ny])//如果两个不同的话 
				{
					//若要保证联通则必须更改 
					if (ans[x][y] + 1 < ans[nx][ny])
					{
						ans[nx][ny] = ans[x][y] + 1;
						nc = c;
						if (nx == n && ny == m) return;
						heap.push((node) {ans[nx][ny],nx,ny,nc});
					}
				}
				else
				{
					//否则不需要更改 
					if (ans[x][y] < ans[nx][ny])
					{
						ans[nx][ny] = ans[x][y];
						if (nx == n && ny == m) return;
						heap.push((node) {ans[nx][ny],nx,ny,Map[nx][ny]});
					}
				}
			}
		}
	}
}
int main()
{
	start.x = 1,start.y = 1,start.c = 92;
	read(t);
	while (t--)
	{
		read(n),read(m);
		prework();
		for (rg int i = 1;i <= n;++i) scanf("%s",Map[i] + 1);
		if (Map[1][1] == '/') ++ans[1][1],Map[1][1] = 92;//ASCII
		start.w = ans[1][1];
		if ((n & 1) && !(m & 1))
		{
			puts("NO SOLUTION");
			continue;
		}
		if (!(n & 1) && (m & 1))
		{
			puts("NO SOLUTION");
			continue;
		}
		boy_friend_search();
		print(ans[n][m]),__endl;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Here-is-SG/p/10519274.html