[bzoj]1295: [SCOI2009]最长距离
原题链接
1295: 最长距离
题意
题目要求的是最远的两个点的距离,要求这两个点在同一个连通块里面。可以去掉障碍物,但是要求去掉的障碍物不能超过T。
分析
啥,同个连通块??搜索??
Boom..
注意到:
- 在同一个连通块里面不管如何走,不用去掉障碍物就能拓展距离,记费用为0。
- 在要去掉障碍物时,我们记费用为1。
那么,我们就可以用最短路的算法对问题进行求解了。
枚举每一个点(a,b)为起点:
- 在图上跑SPFA,最终得到一个二维的cost数组。
- 再枚举另一个点(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]);
}
}
}
}
}