July15th 回家【推荐】Go home 题解

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);
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值