[SCOI2009]最长距离

Description
windy有一块矩形土地,被分为 NM 块 11 的小格子。 有的格子含有障碍物。 如果从格子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 1
3 3 0
001
001
110

Sample Output 1
1.414214

Sample Output 2
3.605551

Sample Input 2
4 3 0
001
001
011
000

Sample Output 3
2.828427

Sample Input 3
3 3 1
001
001
001

HINT
20%的数据,满足 1 <= N,M <= 30 ; 0 <= T <= 0 。 40%的数据,满足 1 <= N,M <= 30 ; 0 <= T <= 2 。 100%的数据,满足 1 <= N,M <= 30 ; 0 <= T <= 30 。


N,M很小,我们可以直接跑N×M次SPFA,求出任意两点之间经过最少障碍数,然后\(N^2\)枚举,判断障碍数,直接统计答案

/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
    static char buf[1000000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
inline int frd(){
    int x=0,f=1;char ch=gc();
    for (;ch<'0'||ch>'9';ch=gc())   if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline int read(){
    int x=0,f=1;char ch=getchar();
    for (;ch<'0'||ch>'9';ch=getchar())  if (ch=='-')    f=-1;
    for (;ch>='0'&&ch<='9';ch=getchar())    x=(x<<1)+(x<<3)+ch-'0';
    return x*f;
}
inline void print(int x){
    if (x<0)    putchar('-'),x=-x;
    if (x>9)    print(x/10);
    putchar(x%10+'0');
}
const int N=30;
const int dx[4]={-1,1,0,0};
const int dy[4]={0,0,-1,1};
int dist[N+10][N+10][N+10][N+10];
int n,m,T;
struct S1{
    int x,y;
    void insert(int _x,int _y){x=_x,y=_y;}
}h[N*N+10];
char map[N+10][N+10];
bool vis[N+10][N+10];
bool in_map(int x,int y){return x>0&&x<=n&&y>0&&y<=m;}
void SPFA(int x,int y,int dis[N+10][N+10]){
    memset(vis,0,sizeof(vis));
    h[1].insert(x,y),dis[x][y]=(map[x][y]=='1'),vis[x][y]=1;
    int head=0,tail=1;
    while (head!=tail){
        if (++head>N*N) head=1;
        int Nx=h[head].x,Ny=h[head].y;
        for (int k=0;k<4;k++){
            int tx=Nx+dx[k],ty=Ny+dy[k];
            if (in_map(tx,ty)&&dis[tx][ty]>dis[Nx][Ny]+(map[tx][ty]=='1')){
                dis[tx][ty]=dis[Nx][Ny]+(map[tx][ty]=='1');
                if (!vis[tx][ty]){
                    if (++tail>N*N) tail=1;
                    h[tail].insert(tx,ty);
                    vis[tx][ty]=1;
                }
            }
        }
        vis[Nx][Ny]=0;
    }
}
int main(){
    n=read(),m=read(),T=read();
    memset(dist,63,sizeof(dist));
    for (int i=1;i<=n;i++)  scanf("%s",map[i]+1);
    for (int i=1;i<=n;i++)
        for (int j=1;j<=n;j++)
            SPFA(i,j,dist[i][j]);
    double Ans=0;
    for (int ox=1;ox<=n;ox++)
        for (int oy=1;oy<=m;oy++)
            for (int ex=1;ex<=n;ex++)
                for (int ey=1;ey<=m;ey++)
                    if (dist[ox][oy][ex][ey]<=T)
                        Ans=max(Ans,sqrt(sqr(ex-ox)+sqr(ey-oy)));
    printf("%.6lf\n",Ans);
    return 0;
}

转载于:https://www.cnblogs.com/Wolfycz/p/9993650.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值