题目大意:
给定一张网格图,求图上删掉T个障碍物之后能联通的两点的最大欧几里德距离是多少。
题解:
预处理两点间路径经过的最小障碍物数,判断是否小于T,更新答案。
代码:
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#define mp make_pair
#define pr pair<int,int>
#define sc second
using namespace std;
int n,m,T,cnt,dis[905],vis[905],f[905][905],a[35][35],last[905];
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
char s[35];
struct node{
int to,next,val;
}e[10005];
priority_queue<pr,vector<pr>,greater<pr> > q;
int calc(int x,int y){
return (x-1)*m+y;
}
void Dijkstra(int st){
for (int i=1; i<=n*m; i++) dis[i]=1e9,vis[i]=0;
dis[st]=0;
q.push(mp(0,st));
while (!q.empty()){
int x=q.top().sc;
q.pop();
if (vis[x]) continue;
vis[x]=1;
for (int i=last[x]; i; i=e[i].next){
int V=e[i].to;
if (dis[V]>dis[x]+e[i].val){
dis[V]=dis[x]+e[i].val;
q.push(mp(dis[V],V));
}
}
}
for (int i=1; i<=n*m; i++) f[st][i]=dis[i];
}
void add(int a,int b,int c){
e[++cnt].to=b;
e[cnt].next=last[a];
e[cnt].val=c;
last[a]=cnt;
}
int main(){
scanf("%d%d%d",&n,&m,&T);
for (int i=1; i<=n; i++){
scanf("%s",s+1);
for (int j=1; j<=m; j++)
if (s[j]=='1') a[i][j]=1;
}
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
for (int k=0; k<4; k++){
int fx=i+dx[k],fy=j+dy[k];
if (fx<1 || fx>n || fy<1 || fy>m) continue;
add(calc(i,j),calc(fx,fy),a[fx][fy]);
}
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
Dijkstra(calc(i,j));
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
if (a[i][j]){
for (int k=1; k<=n*m; k++)
f[calc(i,j)][k]++;
}
double maxx=0;
for (int x1=1; x1<=n; x1++)
for (int y1=1; y1<=m; y1++)
for (int x2=1; x2<=n; x2++)
for (int y2=1; y2<=m; y2++)
if (f[calc(x1,y1)][calc(x2,y2)]<=T) maxx=max(maxx,sqrt((double)(x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
printf("%lf\n",maxx);
return 0;
}