题意
给出n*m的图,每个格点为1或0,1代表到此格点是一个障碍物.在可以移除t块障碍物的条件下。
问所有互相可达的两点中,欧几里得距离最大的为多少。
题解
百度搜了一下原题数据范围才敢写....数据范围是<=30所以最多只有30*30=900个格点,可以求出每两点最少经过多少个障碍物后,枚举两点满足两点间障碍物<=t的最远距离。
求解每两点间建筑物可以对相邻点建图使用最短路堆优化dijkstra复杂度为
code
#include <bits/stdc++.h> #define reg register #define ll long long #define ull unsigned long long #define pii pair<int,int> #define inf 0x3f3f3f3f #define eps 1e-8 #define pi acos(-1.0) #define e exp(1.0) #define ios ios::sync_with_stdio(false) #define rep(i,l,r) for(int i=(l);i<(r);i++) using namespace std; const int maxn = 2e3 + 10; const int mod = 1e9 + 7; struct Edge{ int to,cost,nxt; }edges[maxn << 2]; int g[maxn][maxn]; int head[maxn]; int tot = 0; int dis[maxn][maxn]; int n,m,T; int vis[maxn]; int dir[4][2] = {0,1,1,0,0,-1,-1,0}; inline int id(int i,int j) { return i * m + j; } void addedge(int u,int v,int w) { edges[tot] = {v,w,head[u]}; head[u] = tot++; } void dij(int s) { dis[s][s] = g[s/m][s%m]; vis[s] = 1; priority_queue<pii,vector<pii>,greater<> > pq; pq.push({0,s}); while(!pq.empty()){ pii hd = pq.top(); pq.pop(); for(int i = head[hd.second];i != -1;i = edges[i].nxt){ int to = edges[i].to; int cost = edges[i].cost; if(vis[to]) continue; if(dis[s][to] > dis[s][hd.second] + cost){ dis[s][to] = dis[s][hd.second] + cost; pq.push({dis[s][to],to}); vis[to] = 1; } } } } int dist(int a,int b) { int x1 = a/m,x2 = b/m; int y1 = a%m,y2 = b%m; return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1); } int main() { memset(head,-1,sizeof(head)); tot = 0; scanf("%d%d%d",&n,&m,&T); getchar(); for(int i = 0;i < n;++i){ for(int j = 0;j < m;++j){ char ch = getchar(); g[i][j] = ch - '0'; } getchar(); } for(int i = 0;i < n;++i)for(int j = 0;j < m;++j){ for(int k = 0;k < 4;++k){ int nx = i + dir[k][0],ny = j + dir[k][1]; if(nx >= 0 && nx < n && ny >= 0 && ny < m){ int s = id(i,j),t = id(nx,ny); addedge(s,t,g[nx][ny]); addedge(t,s,g[i][j]); } } } for(int i = 0;i < n;++i)for(int j = 0;j < m;++j) for(int k = 0;k < n;++k)for(int l = 0;l < m;++l){ int s = id(i,j),t = id(k,l); dis[s][t] = inf; } for(int i = 0;i < n;++i) for(int j = 0;j < m;++j) { memset(vis,0,sizeof(vis)); dij(id(i,j)); } int res = 0; for(int i = 0;i < n;++i)for(int j = 0;j < m;++j) for(int k = 0;k < n;++k)for(int l = 0;l < m;++l){ int s = id(i,j),t = id(k,l); if(dis[s][t] <= T){ res = max(res,dist(s,t)); } } printf("%.6lf\n",sqrt(res)); return 0; }