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
输出最佳路径中最小的危险系数。
Solution
将Monster的位置存入队列,作为初始状态,利用SPFA更新出矩阵的危险系数. (危险系数越大越安全?智障?)
二分答案,利用Bfs检索合法性.
Program
C++
#include<iostream>
#include<fstream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m,sx,sy,ex,ey,t,l[501][501],d[1000001][3];
string c;
int me[5][3]={{0,0,0},{0,0,1},{0,1,0},{0,-1,0},{0,0,-1}};
bool bj[501][501];
void SPFA(int j);
bool Bfs(int q);
int FF(int l,int r);
int main()
{
memset(l,10000,sizeof(l));
scanf("%d%d\n",&n,&m);
for (int i=1;i<=n;i++)
{
cin>>c;
for (int j=1;j<=m;j++)
{
switch (c[j-1])
{
case '+':
t++;
d[t][1]=i;
d[t][2]=j;
bj[i][j]=true;
l[i][j]=0;
break;
case 'V':
sx=i;
sy=j;
break;
case 'J':
ex=i;
ey=j;
break;
}
}
//scanf("\n");
}
SPFA(t);
printf("%d",FF(0,n+m));
}
void SPFA(int j)
{
int i=0,p,q;
while (i<j)
{
i++;
for (int k=1;k<=4;k++)
{
p=d[i][1]+me[k][1];
q=d[i][2]+me[k][2];
if ((p>0)&&(p<n+1)&&(q>0)&&(q<m+1))
{
if (l[d[i][1]][d[i][2]]+1<l[p][q])
{
l[p][q]=l[d[i][1]][d[i][2]]+1;
if (!bj[p][q])
{
j++;
d[j][1]=p;
d[j][2]=q;
bj[p][q]=true;
}
}
}
}
bj[d[i][1]][d[i][2]]=false;
}
}
bool Bfs(int q)
{
int i,j,x,y;
memset(bj,false,sizeof(bj));
if (l[sx][sy]<q)
return false;
d[1][1]=sx;
d[1][2]=sy;
bj[sx][sy]=true;
i=0;
j=1;
while (i<j)
{
i++;
for (int k=1;k<=4;k++)
{
x=d[i][1]+me[k][1];
y=d[i][2]+me[k][2];
if ((x>0)&&(x<n+1)&&(y>0)&&(y<m+1)&&(l[x][y]>=q)&&(!bj[x][y]))
{
bj[x][y]=true;
j++;
d[j][1]=x;
d[j][2]=y;
if ((ex==x)&&(ey==y))
return true;
}
}
}
return false;
}
int FF(int l,int r)
{
if (l>=r)
return l;
int m=(l+r)/2+1;
if (Bfs(m))
return FF(m,r);
else
return FF(l,m-1);
}
Pascal
uses
math;
var
n,m,i,j,k,sx,sy,ex,ey,t:longint;
l:array [1..500,1..500] of longint;
d:array [1..1000000,1..2] of longint;
me:array [1..4,1..2] of longint=((0,1),(1,0),(-1,0),(0,-1));
bj:array [1..500,1..500] of boolean;
c:char;
procedure SPFA(j:longint);
var
i,k,p,q:longint;
begin
i:=0;
while i<j do
begin
inc(i);
for k:=1 to 4 do
begin
p:=d[i][1]+me[k][1];
q:=d[i][2]+me[k][2];
if (p>0) and (p<n+1) and (q>0) and (q<m+1) then
begin
if l[d[i][1]][d[i][2]]+1<l[p][q] then
begin
l[p][q]:=l[d[i][1]][d[i][2]]+1;
if not bj[p][q] then
begin
inc(j);
d[j][1]:=p;
d[j][2]:=q;
bj[p][q]:=true;
end;
end;
end;
end;
bj[d[i][1]][d[i][2]]:=false;
end;
end;
function Bfs(q:longint):boolean;
var
i,j,k,x,y:longint;
begin
fillchar(bj,sizeof(bj),false);
if l[sx][sy]<q then
exit(false);
d[1][1]:=sx;
d[1][2]:=sy;
bj[sx][sy]:=true;
i:=0;
j:=1;
while i<j do
begin
inc(i);
for k:=1 to 4 do
begin
x:=d[i][1]+me[k][1];
y:=d[i][2]+me[k][2];
if (x>0) and (x<n+1) and (y>0) and (y<m+1) and (l[x][y]>=q) and (not bj[x][y]) then
begin
bj[x][y]:=true;
inc(j);
d[j][1]:=x;
d[j][2]:=y;
if (ex=x) and (ey=y) then
exit(true);
end;
end;
end;
exit(false);
end;
function find(l,r:longint):longint;
var
m:longint;
begin
if l>=r then
exit(l);
m:=(l+r) shr 1+1;
if Bfs(m) then
exit(find(m,r))
else
exit(find(l,m-1));
end;
begin
assign(input,'init.in');
reset(input);
fillchar(l,sizeof(l),$7f);
readln(n,m);
for i:=1 to n do
begin
for j:=1 to m do
begin
read(c);
case c of
'+':
begin
inc(t);
d[t][1]:=i;
d[t][2]:=j;
bj[i][j]:=true;
l[i][j]:=0;
end;
'V':
begin
sx:=i;
sy:=j;
end;
'J':
begin
ex:=i;
ey:=j;
end;
end;
end;
readln;
end;
SPFA(t);
writeln(find(0,n+m));
end.