Overfencing_usaco2.4.2_bfs

66 篇文章 0 订阅
52 篇文章 0 订阅

题目描述


描述 农夫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个字符表示迷宫

输出格式:


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

说明


翻译来自NOCOW

题解


先暴力找到两个入口,然后直接bfs
因为我们把分隔也算上了,所以答案是(ans+1)/2

代码


/*
ID:wjp13241
PROG:maze1
LANG:C++
*/
/*
ASCII_ :32
*/
#include <stdio.h>
#include <queue>
using namespace std;
struct pos
{
    int x,y;
    pos operator+(pos a)
    {
        return (pos){a.x+x,a.y+y};
    }
};
queue<pos>q;
pos drct[4]={{-1,0},{0,1},{1,0},{0,-1}};
int map[251][251],f[251][251];
int main()
{
    freopen("maze1.in","r",stdin);
    freopen("maze1.out","w",stdout);
    int n,m;
    scanf("%d%d",&m,&n);
    n=n*2+1;
    m=m*2+1;
    char c=getchar();
    for (int i=1;i<=n;i++)
    {
        for (int j=1;j<=m;j++)
        {
            c=getchar();
            map[i][j]=(int)(c);
            f[i][j]=0x7ffffff;
        }
        c=getchar();
    }
    for (int i=1;i<=n;i++)
    {
        if (map[i][1]==32)
        {
            q.push((pos){i,1});
            f[i][1]=0;
        }
        if (map[i][m]==32)
        {
            q.push((pos){i,m});
            f[i][m]=0;
        }
    }
    for (int i=1;i<=m;i++)
    {
        if (map[1][i]==32)
        {
            q.push((pos){1,i});
            f[1][i]=0;
        }
        if (map[n][i]==32)
        {
            q.push((pos){n,i});
            f[n][i]=0;
        }
    }
    while (!q.empty())
    {
        pos now=q.front();q.pop();
        for (int k=0;k<4;k++)
        {
            pos tar=now+drct[k];
            if (tar.x>0&&tar.x<=n&&tar.y>0&&tar.y<=m&&map[tar.x][tar.y]==32&&f[tar.x][tar.y]>f[now.x][now.y]+1)
            {
                q.push(tar);
                f[tar.x][tar.y]=f[now.x][now.y]+1;
            }
        }
    }
    int ans=0;
    for (int i=1;i<=n;i++)
        for (int j=1;j<=m;j++)
            if (map[i][j]==32)
                ans=ans<f[i][j]?f[i][j]:ans;
    printf("%d\n",(ans+1)/2);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值