[bzoj]1295: [SCOI2009]最长距离

原题链接

1295: 最长距离

题意

题目要求的是最远的两个点的距离,要求这两个点在同一个连通块里面。可以去掉障碍物,但是要求去掉的障碍物不能超过T。

分析

啥,同个连通块??搜索??
Boom..
注意到:

  • 在同一个连通块里面不管如何走,不用去掉障碍物就能拓展距离,记费用为0。
  • 在要去掉障碍物时,我们记费用为1。

那么,我们就可以用最短路的算法对问题进行求解了。
枚举每一个点(a,b)为起点:

  1. 在图上跑SPFA,最终得到一个二维的cost数组。
  2. 再枚举另一个点(x,y)作为终点,如果cost[x,y]<=T,更新答案为max

实现是简单umm...
关键是想到最短路吧。

代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <algorithm>
 
using namespace std;
const int dir[4][2]={{-1,0},{0,-1},{1,0},{0,1}};
int n,m,t,dis[35][35];
double ans=-1;
bool g[35][35],vis[35][35];
queue <int> qx,qy;
double cal(int a,int b,int c,int d){
    a=(a-c)*(a-c);
    b=(b-d)*(b-d);
    return sqrt(a+b);
}
void spfa(int x,int y);
void Init();
void work();
int main()
{
    Init();
    work();
    printf("%.6f",ans);
    return 0;
}
void Init(){
    scanf("%d%d%d",&n,&m,&t);
    char c;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            cin>>c;
            if(c=='1')g[i][j]=1;
        }
 
}
void work(){
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            spfa(i,j);
            for(int ii=1;ii<=n;ii++)
                for(int jj=1;jj<=m;jj++)
                    if(dis[ii][jj]<=t)
                        ans=max(ans,cal(i,j,ii,jj));
        }
}
void spfa(int x,int y){
    memset(dis,0x3f,sizeof(dis));
    qx.push(x);qy.push(y);
    dis[x][y]=g[x][y];
    while(qx.size()){
        x=qx.front();qx.pop();
        y=qy.front();qy.pop();
        for(int i=0;i<4;i++){
            if(x+dir[i][0]<1||x+dir[i][0]>n)continue;
            if(y+dir[i][1]<1||y+dir[i][1]>m)continue;
            if(dis[x][y]+g[x+dir[i][0]][y+dir[i][1]]<dis[x+dir[i][0]][y+dir[i][1]]){
                dis[x+dir[i][0]][y+dir[i][1]]=dis[x][y]+g[x+dir[i][0]][y+dir[i][1]];
                if(!vis[x+dir[i][0]][y+dir[i][1]]){
                    qx.push(x+dir[i][0]);
                    qy.push(y+dir[i][1]);
                }
            }
        }
    }
}
posted @ 2018-10-27 00:55  _onglu  阅读(160)  评论(0编辑  收藏  举报