01BFS:Three States

题目:Problem - 590C - Codeforces

用最小的修路格子数,使所有国家都连通。

这道题直接求解比较难,我们可以参考多源BFS:矩阵距离-CSDN博客的求法,正难则反。

根据题意,相同的国家之间一定是连通的。

我们可以求出每个下标到国家1的距离,每个下标到国家2的距离,每个下标到国家3的距离。

  1. 有可能从这个++国家++开始,连通另外两个国家距离最短。
  2. 也有可能从这个++道路++开始,连通另外三个国家距离最短。
  • 遇到道路,权值为1。遇到国家,权值为0(表示不用修路)。

  • 最后遍历所有的点,求出点到所有国家的距离的和,距离最短的就是最优解

  • 情况1:遍历的格子是点(道路)

    • 由于这个点被统计了3次,减去多余统计的2次:x+y+z-2(各个国家为了连到同一个汇合点,需要占用多少个 '.' 这个点被修了三次,实际上只需要修一次就够了)
  • 情况2:遍历的格子是国家

    • x+y+z,因为这个格子本身就不需要修路,所以没有"重复支付这个格子的费用的问题"。
cpp 复制代码
#include <iostream>
#include <deque>
#include <cstring>

using namespace std;
const int N = 1e3+10;
typedef pair<int, int> PII;

int n, m;

char g[N][N];
int dist[4][N][N];

int dx[] = {0, -1, 0, 1};
int dy[] = {1, 0, -1, 0};

void bfs(int num)
{
	deque<PII> q;
	memset(dist[num], -1, sizeof(dist[num]));
	
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			if (g[i][j] - '0' == num)
			{
				dist[num][i][j] = 0;
				q.push_back({i, j});
			}
		}
	}
	
	while(q.size())
	{
		auto t = q.front(); q.pop_front();
		int x1 = t.first, y1 = t.second;
		
		for (int i = 0; i < 4; i++)
		{
			int x2 = x1 + dx[i], y2 = y1 + dy[i];
			
			if (x2 < 1 || y2 < 1 || x2 > n || y2 > m) continue;
			if (g[x2][y2] == '#') continue;
			
			int cnt = 0;
			if (g[x2][y2] == '.') cnt = 1;
			else cnt = 0;
			
			if (dist[num][x2][y2] == -1)
			{
				dist[num][x2][y2] = dist[num][x1][y1] + cnt;
				if (cnt == 1)
				{
					q.push_back({x2, y2});
				}
				else
				{
					q.push_front({x2, y2});
				}
			}
			else
			{
				if (dist[num][x1][y1] + cnt < dist[num][x2][y2])
				{
					dist[num][x2][y2] = dist[num][x1][y1] + cnt;
				}
			}
		}
	}
}

int main()
{
	cin >> n >> m;
	
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			cin >> g[i][j];
		}
	}
	
	bfs(1);
	bfs(2);
	bfs(3);
	
	int ret = 1e6+10, cnt = 0;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			int a = dist[1][i][j], b = dist[2][i][j], c = dist[3][i][j];
			if (g[i][j] == '#' || a == -1 || b == -1 || c == -1 ) continue;
			
			if (g[i][j] == '.') 
			{
				ret = min(ret, a+b+c - 2);
			}
			else
			{
				ret = min(ret, a+b+c);
			}
			
		}
	}
	
	if (ret == 1e6+10) ret = -1;
	
	cout << ret << endl;
	
	return 0;
}
相关推荐
HugoStudio_SWAN12 小时前
洛谷 P1420 / P1179 / B4262 最长连号、数字统计与词频统计——统计的三种面孔
c++·学习·程序人生·算法
青 春 记 忆13 小时前
LeetCode 350. 两个数组的交集 II|Python 解法详解
python·算法·leetcode
阳明山水14 小时前
销量预测2025—2026:从模型竞赛到系统融合的范式转型
人工智能·深度学习·算法·机器学习·架构
桐盛科技14 小时前
拒绝“漂绿”风险:基于边缘计算的碳排放数据清洗算法与实时校验逻辑
人工智能·算法·边缘计算
Tongzhi202614 小时前
通芝科技考勤软件三大发展趋势:AI大模型、无感识别与数据底座
大数据·科技·算法·爬山算法
eBest数字化转型方案15 小时前
Route Optimization for FMCG:多目标排线算法的工程实现
大数据·人工智能·算法
residual_fan16 小时前
持续对比强化学习(Continual Contrastive Reinforcement Learning)论文分享
人工智能·算法·数据挖掘·数据分析
s_w.h16 小时前
【 计网 】序列化与反序列化
linux·服务器·网络·算法·bash
信奥卷王16 小时前
2025年09月GESPC++五级真题解析(含视频)
算法
白狐_79816 小时前
408 数据结构|外部排序:流程与 k 路归并
数据结构·算法