bzoj1295:[SCOI2009]最长距离
题目描述
windy有一块矩形土地,被分为 N*M 块 1*1 的小格子。 有的格子含有障碍物。 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离。 如果从格子A不可以走到格子B,就没有距离。 如果格子X和格子Y有公共边,并且X和Y均不含有障碍物,就可以从X走到Y。 如果windy可以移走T块障碍物,求所有格子间的最大距离。 保证移走T块障碍物以后,至少有一个格子不含有障碍物。
输入
输入文件maxlength.in第一行包含三个整数,N M T。 接下来有N行,每行一个长度为M的字符串,'0'表示空格子,'1'表示该格子含有障碍物。
输出
输出文件maxlength.out包含一个浮点数,保留6位小数。
样例输入
【输入样例一】
3 3 0
001
001
110
【输入样例二】
4 3 0
001
001
011
000
【输入样例三】
3 3 1
001
001
001
3 3 0
001
001
110
【输入样例二】
4 3 0
001
001
011
000
【输入样例三】
3 3 1
001
001
001
样例输出
【输出样例一】
1.414214
【输出样例二】
3.605551
【输出样例三】
2.828427
1.414214
【输出样例二】
3.605551
【输出样例三】
2.828427
提示
20%的数据,满足 1 <= N,M <= 30 ; 0 <= T <= 0 。 40%的数据,满足 1 <= N,M <= 30 ; 0 <= T <= 2 。 100%的数据,满足 1 <= N,M <= 30 ; 0 <= T <= 30 。
题解
数据范围很小,考虑以每一个点为起点跑spfa,dis[i]记录i点到该点的最小障碍物,然后判断能否将这些障碍物删除,更新最大距离。
1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #include<queue> 5 #include<cmath> 6 #define maxn 35 7 #define inf 1<<29 8 using namespace std; 9 queue<int> q; 10 int dx[5]={0,0,1,-1},dy[5]={1,-1,0,0}; 11 int n,m,t,tot,a[maxn*maxn],head[maxn*maxn],vis[maxn*maxn],d[maxn*maxn],ecnt; 12 double ans; 13 char str[35]; 14 struct edge{ 15 int u,v,next; 16 }E[maxn*maxn*4]; 17 void addedge(int u,int v) 18 { 19 E[++ecnt].u=u; 20 E[ecnt].v=v; 21 E[ecnt].next=head[u]; 22 head[u]=ecnt; 23 } 24 int cal(int x,int y){return m*(x-1)+y;} 25 bool ok(int x,int y) 26 { 27 if(x<=0||y<=0||x>n||y>m)return false; 28 return true; 29 } 30 void spfa(int x) 31 { 32 for(int i=1 ; i<=tot; ++i) 33 { 34 d[i]=inf; 35 vis[i]=0; 36 } 37 d[x]=a[x]; 38 vis[x]=1; 39 q.push(x); 40 while(!q.empty()) 41 { 42 int dd=q.front();q.pop(); 43 vis[dd]=0; 44 for(int i=head[dd] ; i ; i=E[i].next ) 45 { 46 int v=E[i].v; 47 if(d[v]>d[dd]+a[v]) 48 { 49 d[v]=d[dd]+a[v]; 50 if(!vis[v]) 51 { 52 vis[v]=1; 53 q.push(v); 54 } 55 } 56 } 57 } 58 } 59 void search(int x,int y,int xx,int yy) 60 { 61 int tmp=cal(xx,yy); 62 if(d[tmp]>t)return ; 63 ans=max(ans,sqrt((xx-x)*(xx-x)+(yy-y)*(yy-y))); 64 } 65 int main() 66 { 67 scanf("%d%d%d",&n,&m,&t); 68 tot=n*m; 69 for(int i=1 ; i<=n ; ++i ) 70 { 71 scanf("%s",str); 72 for(int j=0;j<m;++j) 73 { 74 int k=cal(i,j+1); 75 a[k]=str[j]-'0'; 76 } 77 } 78 for(int i=1 ; i<=n ; ++i ) 79 for(int j=1 ; j<=m ; ++j) 80 { 81 int tmp=cal(i,j); 82 for(int k=0;k<4;++k) 83 { 84 int x=i+dx[k],y=j+dy[k]; 85 if(ok(x,y))addedge(tmp,cal(x,y)); 86 } 87 } 88 for(int i=1 ; i<=n ; ++i ) 89 for(int j=1 ; j<=m ; ++j ) 90 { 91 int tmp=cal(i,j); 92 if(a[tmp]&&!t)continue; 93 spfa(tmp); 94 for(int k=1 ; k<=n ; ++k) 95 for(int p=1 ; p<=m ; ++p) 96 search(i,j,k,p); 97 } 98 printf("%.6lf",ans); 99 return 0; 100 }