1295. [SCOI2009]最长距离【最短路】

Description

windy有一块矩形土地,被分为 N*M 块 1*1 的小格子。 有的格子含有障碍物。 如果从格子A可以走到格子B,那么两个格子的距离就为两个格子中心的欧几里德距离。 如果从格子A不可以走到格子B,就没有距离。 如果格子X和格子Y有公共边,并且X和Y均不含有障碍物,就可以从X走到Y。 如果windy可以移走T块障碍物,求所有格子间的最大距离。 保证移走T块障碍物以后,至少有一个格子不含有障碍物。

Input

输入文件maxlength.in第一行包含三个整数,N M T。 接下来有N行,每行一个长度为M的字符串,'0'表示空格子,'1'表示该格子含有障碍物。

Output

输出文件maxlength.out包含一个浮点数,保留6位小数。

Sample Input

【输入样例一】
3 3 0
001
001
110


【输入样例二】
4 3 0
001
001
011
000


【输入样例三】
3 3 1
001
001
001

Sample Output

【输出样例一】
1.414214

【输出样例二】
3.605551

【输出样例三】
2.828427
 
连向空的边长为0,连向墙的边长为1
 
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<cmath>
 5 #include<queue>
 6 #define N (100+5)
 7 #define id(x,y) (x-1)*m+y
 8 using namespace std;
 9 int n,m,t,a[N][N];
10 double ans;
11 int head[N*N],num_edge;
12 int dis[1001][1001];
13 bool used[N*N];
14 int dx[6]={0,1,-1,0,0},dy[6]={0,0,0,1,-1};
15 char st[N];
16 struct node
17 {
18     int to,next,len;
19 }edge[N*N*N];
20 queue<int>q;
21 
22 void add(int u,int v,int l)
23 {
24     edge[++num_edge].to=v;
25     edge[num_edge].next=head[u];
26     edge[num_edge].len=l;
27     head[u]=num_edge;
28 }
29 
30 void Spfa(int x,int y)
31 {
32     int s=id(x,y);
33     dis[s][s]=0;
34     used[s]=true;
35     q.push(s);
36     while (!q.empty())
37     {
38         int x=q.front(); q.pop();
39         for (int i=head[x];i!=0;i=edge[i].next)
40             if (dis[s][x]+edge[i].len<dis[s][edge[i].to])
41             {
42                 dis[s][edge[i].to]=dis[s][x]+edge[i].len;
43                 if (!used[edge[i].to])
44                 {
45                     used[edge[i].to]=true;
46                     q.push(edge[i].to);
47                 }
48             }
49         used[x]=false;
50     }
51 }
52 
53 int main()
54 {
55     scanf("%d%d%d",&n,&m,&t);
56     for (int i=1;i<=n;++i)
57     {
58         scanf("%s",st);
59         for (int j=1;j<=m;++j)
60             a[i][j]=st[j-1]-'0';
61     }
62     for (int i=1;i<=n;++i)
63         for (int j=1;j<=m;++j)
64             for (int k=1;k<=4;++k)
65                 if (i+dx[k]>=1 && i+dx[k]<=n && j+dy[k]>=1 && j+dy[k]<=m)
66                     add(id(i,j) , id(i+dx[k],j+dy[k]) , a[i+dx[k]][j+dy[k]]);
67 
68     memset(dis,0x7f,sizeof(dis));
69     for (int i=1;i<=n;++i)
70         for (int j=1;j<=m;++j)
71             Spfa(i,j);
72     for (int i=1;i<=n;++i)
73         for (int j=1;j<=m;++j)
74             for (int k=1;k<=n;++k)
75                 for (int l=1;l<=m;++l)
76                     if ( dis[id(i,j)][id(k,l)] + (a[i][j]==1)<=t )
77                         ans=max(ans,sqrt((i-k)*(i-k)+(j-l)*(j-l)));
78     printf("%0.6lf",ans);
79 }

转载于:https://www.cnblogs.com/refun/p/8682372.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值