【搜索】洛谷 P1519 穿越栅栏 Overfencing

题目描述

描述 农夫John在外面的田野上搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口。更幸运的是,他所建造的迷宫是一个“完美的”迷宫:即你能从迷宫中的任意一点找到一条走出迷宫的路。给定迷宫的宽度W(1<=W<=38)及高度H(1<=H<=100)。 2*H+1行,每行2*W+1的字符以下面给出的格式表示一个迷宫。然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的步数(就是从最“糟糕”的一点,走出迷宫的最少步数)。(即使从这一点以最优的方式走向最靠近的出口,它仍然需要最多的步数)当然了,牛们只会水平或垂直地在X或Y轴上移动,他们从来不走对角线。每移动到一个新的方格算作一步(包括移出迷宫的那一步)这是一个W=5,H=3的迷宫:
这里写图片描述
如上图的例子,栅栏的柱子只出现在奇数行或奇数列。每个迷宫只有两个出口。

输入输出格式

输入格式:

第一行: W和H(用空格隔开)

第二行至第2 H + 1行: 每行2 W + 1个字符表示迷宫

输出格式:

输出一个单独的整数,表示能保证牛从迷宫中任意一点走出迷宫的最小步数。

输入输出样例

输入样例#1:

5 3
这里写图片描述
输出样例#1:

9

说明

翻译来自NOCOW

USACO 2.4

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int MAXN=100+5,inf=1000000000;
int w,h,f[MAXN][MAXN],ans=1;
struct node{
    bool north;
    bool south;
    bool east;
    bool west;
    node(){
        north=false;
        south=false;
        east=false;
        west=false;
    }
};
node room[MAXN][MAXN];
inline void read(int &x)
{
    x=0;
    char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while(c>='0'&&c<='9')
    {
        x=x*10+c-'0';
        c=getchar();
    }
}
inline void init()
{
    for(register int i=1;i<=h;++i)
    {
        for(register int j=1;j<=w;++j)f[i][j]=inf;
    }
}
inline bool judge(int x,int y)
{
    if(x<1||x>h||y<1||y>w)return false;
    return true;
}
inline void search(int x,int y)
{
    if(room[x][y].north)
    {
        int dx=x-1,dy=y;
        if(judge(dx,dy)&&(f[x][y]+1<f[dx][dy]))
        {
            f[dx][dy]=f[x][y]+1;
            search(dx,dy);
        }
    }
    if(room[x][y].south)
    {
        int dx=x+1,dy=y;
        if(judge(dx,dy)&&(f[x][y]+1<f[dx][dy]))
        {
            f[dx][dy]=f[x][y]+1;
            search(dx,dy);
        }
    }
    if(room[x][y].east)
    {
        int dx=x,dy=y+1;
        if(judge(dx,dy)&&(f[x][y]+1<f[dx][dy]))
        {
            f[dx][dy]=f[x][y]+1;
            search(dx,dy);
        }
    }
    if(room[x][y].west)
    {
        int dx=x,dy=y-1;
        if(judge(dx,dy)&&(f[x][y]+1<f[dx][dy]))
        {
            f[dx][dy]=f[x][y]+1;
            search(dx,dy);
        }
    }
}
int main()
{
    scanf("%d%d",&w,&h);
    getchar();getchar();
    char c;
    for(register int i=1;i<=2*h+1;++i)
    {
        for(register int j=1;j<=2*w+1;++j)
        {
            scanf("%c",&c);
            if(i%2!=0)
            {
                if(c==' ')
                {
                    int a=(i+1)/2,b=j/2;
                    room[a][b].north=true;
                    room[a-1][b].south=true;
                }
            }
            else
            {
                if(j%2!=0)
                {
                    if(c==' ')
                    {
                        int a=i/2,b=(j+1)/2;
                        room[a][b].west=true;
                        room[a][b-1].east=true;
                    }
                }
            }
        }
        getchar();getchar();
    }
    init();
    for(register int i=1;i<=w;++i)if(room[1][i].north)
    {
        f[1][i]=1;
        search(1,i);
    }
    for(register int i=1;i<=w;++i)if(room[h][i].south)
    {
        f[h][i]=1;
        search(h,i);
    }
    for(register int i=1;i<=h;++i)if(room[i][1].west)
    {
        f[i][1]=1;
        search(i,1);
    }
    for(register int i=1;i<=h;++i)if(room[i][w].east)
    {
        f[i][w]=1;
        search(i,w);
    }
    for(register int i=1;i<=h;++i)
    {
        for(register int j=1;j<=w;++j)ans=max(ans,f[i][j]);
    }
    cout<<ans;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值