cf 591 E.Three States 01bfs
有3个城市,'.'表示空地,可以用于建桥,'#'是城墙。
然后求至少需要建几个桥才能使得3个城市连通。
思路是用01bfs
建立一个数组dis[k][i][j]表示从第k个城市出发到i,j至少要建筑几个桥。
然后进行3次01bfs,因为'.'需要花费,权值是1,所以放在双端队列的尾部,其他放在双端队列的首部,每次都取双端队列的首部进行bfs
最后遍历每个点,在3个城市都能到达的前提下。
int now = dis[0][i][j] + dis[1][i][j] + dis[2][i][j] - 2 * (s[i][j] == '.');
因为'.'算了3次,所以必须要剪掉2次。
就是一种方案,求出最小方案就是答案。
也可以用最短路去求出距离,但最短路的时间复杂度明显高了,对于权值只有0和1的情况下最好用01bfs,时间复杂度低一点
#include <bits/stdc++.h>
#define ll long long
#define ld long double
#define CASE int Kase = 0; cin >> Kase; for(int kase = 1; kase <= Kase; kase++)
using namespace std;
template<typename T = long long> inline T read() {
T s = 0, f = 1; char ch = getchar();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = getchar();}
while(isdigit(ch)) {s = (s << 3) + (s << 1) + ch - 48; ch = getchar();}
return s * f;
}
#ifdef ONLINE_JUDGE
#define qaq(...) ;
#define qwq(c) ;
#else
#define qwq(a, b) for_each(a, b, [=](int x){cerr << x << " ";}), cerr << std::endl
template <typename... T> void qaq(const T &...args) {
auto &os = std::cerr;
(void)(int[]){(os << args << " ", 0)...};
os << std::endl;
}
#endif
const int N = 1e3 + 5, M = 1e6 + 5, MOD = 1e9 + 7, CM = 998244353, INF = 0x3f3f3f3f; const ll linf = 0x7f7f7f7f7f7f7f7f;
char s[N][N];
int dis[4][N][N];
struct Node{
int x, y;
};
int dir[][2] = {1,0, -1,0, 0,1, 0,-1};
void bfs01(int st, int sx, int sy, int n, int m){
deque<Node> q;
q.push_back(Node{sx, sy});
dis[st][sx][sy] = 0;
while(!q.empty()) {
Node tmp = q.front(); q.pop_front();
int x = tmp.x, y = tmp.y;
for(int i = 0; i < 4; i++) {
int xx = x + dir[i][0], yy = y + dir[i][1];
if(xx < 1 || xx > n || yy < 1 || yy > m || s[xx][yy] == '#') continue;
int nowdis = dis[st][x][y] + (s[xx][yy] == '.');
if(nowdis < dis[st][xx][yy]) {
dis[st][xx][yy] = nowdis;
if(s[xx][yy] == '.') q.push_back(Node{xx, yy});
else q.push_front(Node{xx, yy});
}
}
}
}
void solve(int kase){
memset(dis, 0x3f, sizeof(dis));
int n = read(), m = read();
for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
for(int k = 1; k <= 3; k++) {
int x = 0, y = 0;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(s[i][j] == '0' + k) {
x = i, y = j;
}
}
}
bfs01(k - 1, x, y, n, m);
}
int ans = -1;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(dis[0][i][j] != INF && dis[1][i][j] != INF && dis[2][i][j] != INF) {
int now = dis[0][i][j] + dis[1][i][j] + dis[2][i][j] - 2 * (s[i][j] == '.');
if(ans == -1) ans = now;
else ans = min(ans, now);
}
}
}
printf("%d\n", ans);
}
const bool ISFILE = 0, DUO = 0;
int main(){
clock_t start, finish; start = clock();
if(ISFILE) freopen("/Users/i/Desktop/practice/in.txt", "r", stdin);
if(DUO) {CASE solve(kase);} else solve(1);
finish = clock();
qaq("\nTime:", (double)(finish - start) / CLOCKS_PER_SEC * 1000, "ms\n");
return 0;
}
I‘m Stein, welcome to my blog