BZOJ#1295[SCOI2009]最长距离
[SCOI2009]最长距离
思路:
将1的格子变成边权为1,则需要求每个点所能到达的点的最短距离并且不超过t,这里采用01bfs求最短路
代码:
#include <bits/stdc++.h>
#define int long long
int _ = 0, Case = 1;
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'
const int N = 40;
int d[N][N];
char s[N][N];
int n, m, t;
struct T {
int x, y, w;
};
bool vis[N][N];
pair<int, int> moves[] = {{ -1, 0}, {0, -1}, {0, 1}, {1, 0}}; //ULRD
double dist(int x, int y, int a, int b) {
int ta = abs(x - a);
int tb = abs(y - b);
return sqrt(ta*ta + tb*tb);
}
double bfs(int x, int y) {
deque<T> q;
q.push_front({x, y, 0});
memset(d, 0x3f, sizeof d);
d[x][y] = 0;
memset(vis,0,sizeof vis);
while (q.size()) {
auto [x, y, w] = q.front();
q.pop_front();
if (vis[x][y]) continue;
vis[x][y] = true;
for (auto [dx, dy] : moves) {
int tx = x + dx, ty = dy + y;
if (tx >= 1 and tx <= n and ty >= 1 and ty <= m) {
int nw = 0;
if (s[tx][ty] == '1') nw = 1;
if (d[tx][ty] > w + nw) {
d[tx][ty]=w+nw;
if (nw) {
q.push_back({tx, ty, w + nw});
} else {
q.push_front({tx, ty, w + nw});
}
}
}
}
}
double res = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (d[i][j]<=t) {
res = max(res, dist(x, y, i, j));
}
}
}
return res;
}
void solve(int Case) {
scanf("%lld%lld%lld",&n,&m,&t);
double res=0;
for (int i = 1; i <= n; i++) scanf("%s",(s[i]+1));
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
if (s[i][j] == '0') {
res = max(res, bfs(i, j));
}
}
}
printf("%.6lf\n",res);
}
signed main() {
//ios::sync_with_stdio(false); cin.tie(nullptr);
// cin >> _; for (Case = 1; Case <= _; Case++)
solve(Case);
return 0;
}