题目描述
两头白天鹅生活在一个部分湖面结了冰的湖泊中,湖面的形状为一个长方形,并且被分割成R行C列的小方格,某些方格中结了冰,这样的方格称之为冰格,其余的方格称之为水格。冬天过去了,湖面上的冰渐渐开始溶解了,每一天与水相邻的冰格就将消融而转化为水格。所谓两个方格相邻是指它们在水平或垂直方向有公共边,两个呈对角的方格是不相邻的,下图给出样例数据的演化过程。
白天鹅只能在水中沿水平或垂直方向游动,写一个程序判断多少天后两只白天鹅才能够相会。
【输入格式】
输入文件第一行包含两个用空格隔开的整数R和C,其中1 ≤ R, C ≤ 1500,接下来的R行每行包含C个字符,描述湖面的初始状态,‘·’表示水格,‘ X’表示冰格,‘ L’表示一只白天鹅。
【输出格式】
输出文件仅一行包含一个整数表示两只白天鹅等到相邻那一天所需的天数。
【输入样例】
8 17
...XXXXXX..XX.XXX
....XXXXXXXXX.XXX
...XXXXXXXXXXXX..
..XXXXX.LXXXXXX..
.XXXXXX..XXXXXX..
XXXXXXX...XXXX...
..XXXXX...XXX....
....XXXXX.XXXL...
【输出样例】
2
Hint
30%数据1 ≤ R《400.1 ≤ C《300
100%其中1 ≤ R, C ≤ 1500
暴力搜索,手打队列比系统队列快很多,一开始不知道,结果调了好长时间,一直超时
先bfs求出每个冰块融化的最短时间(t[i][j]),把初始时是水的点放入队列,用队列中的点更新周围的点,在bfs求从第一只天鹅到其他点的最短时间(ned[i][j]),显然这个最短时间由她经过的冰块的最长融化时间决定,类似于spfa的一个队列bfs,ned[i][j]=min(ned[i][j].max(ned[x][y],t[x][y])) (x,y)是当前队列的首项,(i,j)是(x,y)周围要更新的点
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<queue>
#define maxn 2505
using namespace std;
int n,m,cnt=0;
struct point
{
int x,y;
}b[3],g[maxn*maxn];
int op=0;
int ti[maxn][maxn],c[maxn][maxn],ned[maxn][maxn];
bool v[maxn][maxn];
char s[maxn];
int q[maxn*maxn*5]={0},h=0,t=0;
void read()
{
h=1;t=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
c[i][j]=++cnt;
g[cnt].x=i;g[cnt].y=j;
}
for(int i=1;i<=n;i++){
scanf("%s",s);
for(int j=0;j<m;j++){
if(s[j]!='X')
{ ti[i][j+1]=0; q[++t]=c[i][j+1]; }
if(s[j]=='L'){ op++;b[op].x=i;b[op].y=j+1; }
}
}
}
void pre()
{
int tmp,now;
int x,y;
while(h<=t){
now=q[h]; h++;
x=g[now].x; y=g[now].y; v[x][y]=0;
if(x+1<=n&&ti[x+1][y]>ti[x][y]+1){
ti[x+1][y]=ti[x][y]+1;
if(!v[x+1][y]){ v[x+1][y]=1; q[++t]=c[x+1][y]; }
}
if(x-1>=1&&ti[x-1][y]>ti[x][y]+1){
ti[x-1][y]=ti[x][y]+1;
if(!v[x-1][y]){ v[x-1][y]=1; q[++t]=c[x-1][y]; }
}
if(y+1<=m&&ti[x][y+1]>ti[x][y]+1){
ti[x][y+1]=ti[x][y]+1;
if(!v[x][y+1]){ v[x][y+1]=1; q[++t]=c[x][y+1]; }
}
if(y-1>=1&&ti[x][y-1]>ti[x][y]+1){
ti[x][y-1]=ti[x][y]+1;
if(!v[x][y-1]){ v[x][y-1]=1; q[++t]=c[x][y-1]; }
}
}
}
void bfs()
{
memset(ned,0xf,sizeof(ned));
memset(v,0,sizeof(v));
memset(q,0,sizeof(q));
h=1;t=0;
int now,tmp;
int x,y;
q[++t]=c[b[1].x][b[1].y];
ned[b[1].x][b[1].y]=0; v[b[1].x][b[1].y]=1;
while(h<=t){
now=q[h]; h++;
x=g[now].x; y=g[now].y; v[x][y]=0;
int ma=max(ned[x][y],ti[x][y]);
if(x+1<=n&&ned[x+1][y]>ma){
ned[x+1][y]=ma;
if(!v[x+1][y]){ q[++t]=c[x+1][y]; v[x+1][y]=1; }
}
if(x-1>=1&&ned[x-1][y]>ma){
ned[x-1][y]=ma;
if(!v[x-1][y]){ q[++t]=c[x-1][y]; v[x-1][y]=1; }
}
if(y+1<=m&&ned[x][y+1]>ma){
ned[x][y+1]=ma;
if(!v[x][y+1]){ q[++t]=c[x][y+1]; v[x][y+1]=1; }
}
if(y-1>=1&&ned[x][y-1]>ma){
ned[x][y-1]=ma;
if(!v[x][y-1]){ q[++t]=c[x][y-1]; v[x][y-1]=1; }
}
}
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("swan.in","r",stdin);
//freopen("swan.out","w",stdout);
memset(ti,0xf,sizeof(ti));
read();pre();
bfs();
printf("%d",ned[b[2].x][b[2].y]);
// while(1);
return 0;
}