ALice回家题解
嗯哼。
Description
Alice住在森林里,森林可以看作是N*M的网格,森林里有怪兽,用‘.’表示空地,‘+’表示怪兽,‘V’表示Alice现在的位置,‘J’表示Alice的家。
Alice可以从当前单元格向上下左右相邻单元格移动,有怪兽的地方也可以走,只不过比较危险,有怪兽的单元格对其他单元格会产生一定的危险系数,假设怪兽位置为(A,B),它对某单元格(R,C)的危险系数为:|R-A|+|C-B|,危险系数越小越危险,每个单元格的危险系数是所有怪兽对它产生的系数的最小值。
Alice请你帮她找一条最佳路径回家,即使得路径上经过单元格的最小的危险系数最大。
Input
输入第一行包含两个整数N和M(1<=N,M<=500),表示森林的大小。
接下来N行每行包含M个字符:‘.’,‘+’,‘V’,‘J’。
输入只包含一个‘V’和‘J’,而且至少有一个‘+’。
Output
输出最佳路径中最小的危险系数。
题解:!!!BFS+二分!
代码:
Pascal
var
i,j,k,n,s,t,m,s1,s2,h1,h2:longint;
d:array[0..1000000,1..3]of longint;
f:array[0..1000000,1..2]of longint;
c:array[0..1000,0..1000]of char;
data:array[0..1000,0..1000]of longint;
move:array[1..4,1..2]of longint=((1,0),(0,1),(-1,0),(0,-1));
l,r,x:longint;
bj:array[0..1000,0..1000]of boolean;
procedure work;
var
i,j,k,x,y:longint;
begin
fillchar(bj,sizeof(bj),0);
fillchar(d,sizeof(d),0);
for i:=1 to f[0,1] do
begin
d[i,1]:=f[i,1];
d[i,2]:=f[i,2];
d[i,3]:=0;
bj[f[i,1],f[i,2]]:=true;
data[f[i,1],f[i,2]]:=0;
end;
i:=0;
j:=f[0,1];
while i<j do
begin
inc(i);
for k:=1 to 4 do
begin
x:=d[i,1]+move[k,1];
y:=d[i,2]+move[k,2];
if not bj[x,y] then
begin
if (x>0)and(x<=n)and(y>0)and(y<=m) then
begin
inc(j);
d[j,1]:=x;
d[j,2]:=y;
d[j,3]:=d[i,3]+1;
data[x,y]:=d[j,3];
bj[x,y]:=true;
end;
end;
end;
end;
end;
function prepare(t:longint):boolean;
var
i,j,k,x,y:longint;
begin
fillchar(bj,sizeof(bj),false);
fillchar(d,sizeof(d),false);
i:=0;
j:=1;
d[1,1]:=s1;
d[1,2]:=s2;
bj[s1,s2]:=true;
while i<j do
begin
inc(i);
for k:=1 to 4 do
begin
x:=d[i,1]+move[k,1];
y:=d[i,2]+move[k,2];
if (x=h1)and(y=h2) then
begin
exit(true);
end;
if not bj[x,y] then
begin
if (x>0)and(x<=n)and(y>0)and(y<=m)and(data[x,y]>=t) then
begin
inc(j);
d[j,1]:=x;
d[j,2]:=y;
bj[x,y]:=true;
end;
end;
end;
end;
exit(false);
end;
begin
fillchar(data,sizeof(data),$7f);
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(c[i,j]);
if c[i,j]='+' then
begin
inc(f[0,1]);
f[f[0,1],1]:=i;
f[f[0,1],2]:=j;
end;
if c[i,j]='J' then
begin
h1:=i;
h2:=j;
end;
if c[i,j]='V' then
begin
s1:=i;
s2:=j;
end;
end;
readln;
end;
work;
l:=0;
r:=data[s1,s2];
//writeln(data[s1,s2]);
while l<r do
begin
x:=(l+r+1) div 2;
if prepare(x) then l:=x
else r:=x-1;
end;
writeln(l);
end.
C++
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#define fo(i,x,y) for(int i=x;i<=y;i++)
using namespace std;
int f[505][505],w[250005][3],i,j,k,ans,x,y,z,v,n,m,len,mid,l,r;
int fx[4]={0,1,0,-1};
int fy[4]={-1,0,1,0};
char map[505][505];
bool bz[505][505],rr[505][505];
bool b[505][505];
void dfs(int x,int y)
{
int t,ww;
w[1][1]=x;
w[1][2]=y;
t=0;ww=1;
bz[x][y]=true;
while (t<ww)
{
t++;
fo(i,0,3)
{
int p=w[t][1]+fx[i];
int h=w[t][2]+fy[i];
if (p<=0 || p>n || h<=0 || h>m) continue;
if (bz[p][h]==false)
{
ww++;
w[ww][1]=p;
w[ww][2]=h;
bz[p][h]=true;
if (map[p][h]=='J') return;
}
}
}
}
void bfs()
{
int t,ww;
t=0;ww=len;
while (t<ww)
{
t++;
int x=w[t][1];
int y=w[t][2];
fo(i,0,3)
{
int p=x+fx[i];
int h=y+fy[i];
if (p<=0 || p>n || h<=0 || h>m) continue;
if (f[x][y]+1<f[p][h])
{
f[p][h]=f[x][y]+1;
if (b[p][h]==false)
{
ww++;
w[ww][1]=p;
w[ww][2]=h;
b[p][h]=true;
}
}
}
b[x][y]=false;
}
}
int main()
{
memset(b,false,sizeof(b));
scanf("%d%d",&n,&m);
fo(i,1,n)
{
scanf("\n");
fo(j,1,m) scanf("%c",&map[i][j]);
}
memset(f,0x7f,sizeof(f));
len=0;
fo(i,1,n)
{
fo(j,1,m)
{
if (map[i][j]=='+')
{
b[i][j]=true;
f[i][j]=0;
len++;
w[len][1]=i;
w[len][2]=j;
}
if (map[i][j]=='V'){x=i;y=j;}
if (map[i][j]=='J'){z=i;v=j;}
}
}
bfs();
l=0;r=f[x][y];
if (r>f[z][v]) r=f[z][v];
while (l<=r)
{
memset(bz,false,sizeof(bz));
mid=(l+r)/2;
fo(i,1,n)
fo(j,1,m)
if (f[i][j]<mid) bz[i][j]=true;
dfs(x,y);
if (bz[z][v])
{
l=mid+1;
ans=mid;
}else r=mid-1;
}
printf("%d",ans);
}