DFS + 暴力枚举
思路:
先判断起点能不能达到终点,如果能输出 0
dfs(sx, sy, st1);
if (st1[tx][ty]) puts("0");
预处理所有从起点能到达的点和终点能到达的点,暴力枚举两个集合中的点,计算两个点的最小距离就是答案
关键代码(dfs):
用 st1 记录可以从起点到达的每个点,st2 记录终点可以到达的每个点
dfs:先把能到达的这个点标记为true
再枚举上下左右四个方向,如果在范围内且没有标记并且能达到,则dfs这个点。
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
bool st1[N][N], st2[N][N];
void dfs(int x, int y, bool st[][N])
{
st[x][y] = true;
for (int i = 0; i < 4; i ++ )
{
int a = x + dx[i], b = y + dy[i];
if (a >= 0 && a < n && b >= 0 && b < n && !st[a][b] && g[a][b] == '0')
dfs(a, b, st);
}
}
完整代码:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 55;
int n;
char g[N][N];
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
bool st1[N][N], st2[N][N];
void dfs(int x, int y, bool st[][N])
{
st[x][y] = true;
for (int i = 0; i < 4; i ++ )
{
int a = x + dx[i], b = y + dy[i];
if (a >= 0 && a < n && b >= 0 && b < n && !st[a][b] && g[a][b] == '0')
dfs(a, b, st);
}
}
int main()
{
cin >> n;
int sx, sy, tx, ty;
cin >> sx >> sy >> tx >> ty;
sx --, sy --, tx --, ty -- ;
for (int i = 0; i < n; i ++ ) cin >> g[i];
dfs(sx, sy, st1);
if (st1[tx][ty]) puts("0");
else
{
dfs(tx, ty, st2);
int res = 1e8;
for (int i = 0; i < n; i ++ )
for (int j = 0; j < n; j ++ )
if (st1[i][j])
for (int x = 0; x < n; x ++ )
for (int y = 0; y < n; y ++ )
if (st2[x][y])
res = min(res, (i - x) * (i - x) + (j - y) * (j - y));
cout << res << endl;
}
return 0;
}