【传送门:BZOJ1295】
简要题意:
给出一个n*m的矩阵,有障碍物,(a,b)和(c,d)存在距离当且仅当两个点能互相到达,且距离为欧几里德距离
可以移走t个障碍物,求出距离最大的两个点的距离
题解:
n,m这么这么小
直接O(n2m2),跑最短路,水题
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> using namespace std; bool v[31][31]; int d[31][31]; int n,m; struct node { int x,y; }list[1100]; char st[31][31]; int dx[5]={0,1,-1,0,0}; int dy[5]={0,0,0,1,-1}; void spfa(int sx,int sy) { memset(d,63,sizeof(d));d[sx][sy]=st[sx][sy]-'0'; memset(v,false,sizeof(v));v[sx][sy]=true; list[1].x=sx;list[1].y=sy; int head=1,tail=2; while(head!=tail) { int x=list[head].x,y=list[head].y; for(int i=1;i<=4;i++) { int tx=x+dx[i],ty=y+dy[i]; if(tx<1||ty<1||tx>n||ty>m) continue; if(d[tx][ty]>d[x][y]+st[tx][ty]-'0') { d[tx][ty]=d[x][y]+st[tx][ty]-'0'; if(v[tx][ty]==false) { v[tx][ty]=true; list[tail].x=tx; list[tail].y=ty; tail++;if(tail==n*m+1) tail=1; } } } v[x][y]=false; head++;if(head==n*m+1) head=1; } } int main() { int t; scanf("%d%d%d",&n,&m,&t); for(int i=1;i<=n;i++) scanf("%s",st[i]+1); double ans=0.0; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { spfa(i,j); for(int a=1;a<=n;a++) { for(int b=1;b<=m;b++) { if(d[a][b]<=t&&(a!=i||b!=j)) { ans=max(ans,sqrt(double((i-a)*(i-a)+(j-b)*(j-b)))); } } } } } printf("%.6lf ",ans); return 0; }