废话
记录一下遇到的第二个01bfs问题,01bfs和bfs的区别在于路径权值只有0和1,这个时候就优先搞权值为0的边,就用双端队列deque存储,如果边权为0,在前面插入,否则的话在后面插入,比正常跑bfs速度快很多
题目链接
https://ac.nowcoder.com/acm/problem/111125
题面
The famous global economic crisis is approaching rapidly, so the states of Berman, Berance and Bertaly formed an alliance and allowed the residents of all member states to freely pass through the territory of any of them. In addition, it was decided that a road between the states should be built to guarantee so that one could any point of any country can be reached from any point of any other State.
Since roads are always expensive, the governments of the states of the newly formed alliance asked you to help them assess the costs. To do this, you have been issued a map that can be represented as a rectangle table consisting of n rows and m columns. Any cell of the map either belongs to one of three states, or is an area where it is allowed to build a road, or is an area where the construction of the road is not allowed. A cell is called passable, if it belongs to one of the states, or the road was built in this cell. From any passable cells you can move up, down, right and left, if the cell that corresponds to the movement exists and is passable.
Your task is to construct a road inside a minimum number of cells, so that it would be possible to get from any cell of any state to any cell of any other state using only passable cells.
It is guaranteed that initially it is possible to reach any cell of any state from any cell of this state, moving only along its cells. It is also guaranteed that for any state there is at least one cell that belongs to it.
题目大意
- 给定一个n * m 的矩阵,其中有1 , 2 , 3组成的连通块,表示三个州,然后 · 表示可修建路,花费为1,#表示不可走,问最少花费多少,可是三个州联通
策略
最优的情况肯定是通过某一点向三个连通块的花费最小。这个点可能是三大连通块之一,可能是 · , 如果是三大联通快,就直接是dis1 + dis2 + dis3 , 否则的话, · 这个到三连通块的距离在最优的情况下,只有一个 · 这个点重复走了三次,那么只需要走一次,dis1 + dis2 + dis3 - 2 ,
最优情况下, 某个点到三大联通块的三条路径中唯一的交叉点一定是被枚举的某一点
那么我们就是求出每个点到三个连通块的距离,反过来从每个连通块求到所有点的最短距离,最后枚举一下所有点即可
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <map>
#include <list>
#include <queue>
#include <cstring>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <stack>
#include <set>
#include <deque>
#pragma GCC optimize(3 , "Ofast" , "inline")
using namespace std ;
#define ios ios::sync_with_stdio(false) , cin.tie(0) , cout.tie(0)
#define x first
#define y second
#define ls rt << 1
#define rs rt << 1 | 1
typedef long long ll ;
const double esp = 1e-6 , pi = acos(-1) ;
typedef pair<int , int> PII ;
const int N = 1010 , INF = 0x3f3f3f3f , mod = 1e9 + 7;
int cinint(){ int t ; scanf("%d" , &t) ; return t ;}
int cinll(){ll t ;scanf("%lld" , &t) ;return t ;}
char s[N][N] ;
int n , m ;
int d[4][2] = {1 , 0 , -1 , 0 , 0 , 1 , 0 , -1} ;
int dis[N][N][4] ;
void bfs(int t)
{
deque<PII> q ;
for(int i = 0 ;i < n ;i ++ )
for(int j = 0 ;j < m ;j ++ )
{
dis[i][j][t] = INF ;
if(s[i][j] == t + '0')
q.push_front({i , j}) , dis[i][j][t] = 0 ;
}
while(q.size())
{
auto u = q.front() ;
q.pop_front() ;
for(int i = 0 ;i < 4 ;i ++ )
{
int tx = u.x + d[i][0] , ty = u.y + d[i][1] ;
if(tx < 0 || ty < 0 || tx >= n || ty >= m || s[tx][ty] == '#') continue ;
int w = s[tx][ty] == '.' ;
if(dis[tx][ty][t] > dis[u.x][u.y][t] + w)
{
dis[tx][ty][t] = dis[u.x][u.y][t] + w ;
if(w) q.push_back({tx , ty}) ;
else q.push_front({tx , ty}) ;
}
}
}
}
int work()
{
n = cinint() , m = cinint() ;
for(int i = 0 ;i < n ;i ++ ) scanf("%s" , s[i]) ;
bfs(1) , bfs(2) , bfs(3) ;
ll ans = 1e18 ;
for(int i = 0 ;i < n ;i ++ )
for(int j = 0 ;j < m ;j ++ )
{
ll res = 1ll * dis[i][j][1] + dis[i][j][2] + dis[i][j][3] ;
if(s[i][j] == '.') res -= 2 ;
ans = min(1ll * ans , res) ;
}
if(ans > n * m) puts("-1") ;
else cout << ans << endl ;
return 0 ;
}
int main()
{
work() ;
return 0 ;
}
/*
*/