给一个n*n的图,0表示地面,1表示水,给出起点和终点,
现要从起点到达终点,有一次在两个坐标间创立隧道的机会,消耗为(x1 - x2)^2 + (y1 - y1)^2。
求出最小的消耗,如果直接能走到,则消耗为0。
bfs求出起点和终点分别能到达的点,枚举每一种情况,取最小值即可。
#include <bits/stdc++.h> using namespace std; typedef long long LL; int Next[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; const int MAXN = 50 + 5; char Map[MAXN][MAXN]; int vis[MAXN][MAXN]; int n, r1, r2, c1, c2; int Bfs() { queue<pair<int, int>> que; vector<pair<int, int>> start; vector<pair<int, int>> ends; que.push(make_pair(r1, c1)); vis[r1][c1] = 1; while (!que.empty()) { int x = que.front().first; int y = que.front().second; start.push_back(make_pair(x, y)); if (x == r2 && y == c2) return 0; for (int i = 0;i < 4;i++) { int nx = x + Next[i][0]; int ny = y + Next[i][1]; if (nx < 1 || nx > n || ny < 1 || ny > n) continue; if (vis[nx][ny] || Map[nx][ny] == ‘1‘) continue; vis[nx][ny] = 1; que.push(make_pair(nx, ny)); } que.pop(); } que.push(make_pair(r2, c2)); vis[r2][c2] = 1; while (!que.empty()) { int x = que.front().first; int y = que.front().second; ends.push_back(make_pair(x, y)); for (int i = 0;i < 4;i++) { int nx = x + Next[i][0]; int ny = y + Next[i][1]; if (nx < 1 || nx > n || ny < 1 || ny > n) continue; if (vis[nx][ny] || Map[nx][ny] == ‘1‘) continue; vis[nx][ny] = 1; que.push(make_pair(nx, ny)); } que.pop(); } int res = 9999; /* for (int i = 0;i < start.size();i++) cout << start[i].first << ‘ ‘ << start[i].second << endl; cout << endl; for (int i = 0;i < ends.size();i++) cout << ends[i].first << ‘ ‘ << ends[i].second << endl; cout << endl; */ for (int i = 0;i < start.size();i++) { for (int j = 0;j < ends.size();j++) { int cx = start[i].first - ends[j].first; int cy = start[i].second - ends[j].second; int cost = cx * cx + cy * cy; res = min(res, cost); } } return res; } int main() { cin >> n; cin >> r1 >> c1 >> r2 >> c2; for (int i = 1;i <= n;i++) { for (int j = 1; j <= n; j++) cin >> Map[i][j]; } cout << Bfs() << endl; return 0; }
原文:https://www.cnblogs.com/YDDDD/p/10447796.html