USACO 2.4.2 穿越栅栏

【问题描述】

  FJ搭建了一个巨大的用栅栏围成的迷宫。幸运的是,他在迷宫的边界上留出了两段栅栏作为迷宫的出口,并且从迷宫中的任意一点都能找到一条走出迷宫的路。给定迷宫的宽 W 及长 H 和这个迷宫,然后计算从迷宫中最“糟糕”的那一个点走出迷宫所需的最少步数。

【输入格式】

  第一行: W和H(用空格隔开)
  第二行至第2*H+1行: 每行2*W+1个字符表示迷宫

【输出格式】

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

【输入样例】

5 3
+-+-+-+-+-+
|         |
+-+ +-+ + +
|     | | |
+ +-+-+ + +
| |     |  
+-+ +-+-+-+

【输出样例】

9

【数据范围】

  1 <= W <= 38
  1 <= H <= 100

之前做过改题,顺便把原题做了。
这道题输入是一张图,因为有空格,因此要用gets输入,注意刚开始gets前处理输入W,H后的换行符。在输入中确定每个格子的墙和两个出口(处理有点麻烦,需要仔细),将两个出口进入队列后进行多源bfs求出最短路径就得出答案。

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
using namespace std;
//0,1,2,3 东南西北;
int w, h, x, y, mat[102][102][4], vis[102][102], d[102][102];
int dx[] = { 0, 1, 0, -1 };
int dy[] = { 1, 0, -1, 0 };
char tu[101],Empty;
struct data
{
    int x, y;
};
queue<data>a;

int bfs()
{
    int ans = 0;
    while (!a.empty())
    {
        data t = a.front(); a.pop();
        for (int i = 0; i<4; i++)
        {
            int nx = t.x + dx[i];
            int ny = t.y + dy[i];
            if (nx<1 || ny<1 || nx>h || ny>w) continue;
            if (mat[t.x][t.y][i] == 1) continue;
            if (vis[nx][ny]) continue;
            vis[nx][ny] = 1;
            d[nx][ny] = d[t.x][t.y] + 1;
            ans = max(d[nx][ny], ans); //寻找最短路径长度最大值
            a.push((data){ nx, ny });
        }
    }
    return ans;
}

int main()
{
    //freopen("1.txt", "r", stdin);
    //freopen("pass.out", "w", stdout);
    scanf("%d%d", &w, &h);
    memset(mat, 0, sizeof(mat));
    memset(vis, 0, sizeof(vis));
    memset(d, 1, sizeof(d));
    int ok=1;
    scanf("%c",&Empty);  //处理换行符
    for(int i=0;i<=2*h;i++)
    {
         gets(tu);
         if(ok==1)
         {
            for(int j=0;j<strlen(tu);j++)
            {
                if(tu[j]=='-')
                {
                    if(i==0)  mat[i/2+1][j/2+1][3]= 1;
                    else if(i==2*h)   mat[i/2][j/2+1][1]=1;
                    else mat[i/2][j/2+1][1]=mat[i/2+1][j/2+1][3]=1;
                }
                else if(tu[j]==' ')
                if(i==2*h||i==0)
                {
                    if(i==0)  x=i/2+1,y=j/2+1;
                    else x=i/2,y=j/2+1;
                    a.push((data){ x, y }); //一个出口
                    vis[x][y] = 1;
                    d[x][y] = 1;
                }
            }
         }
         else if(ok==2)
         {
            for(int j=0;j<strlen(tu);j++)
            {
                if(tu[j]=='|')
                {
                    if(j==0)  mat[i/2+1][j/2+1][2]=1;
                    else if(j==2*w)  mat[i/2+1][j/2][0]=1;
                    else mat[i/2+1][j/2][0]=mat[i/2+1][j/2+1][2]=1;
                 }
                else if(tu[j]==' ')
                if(j==0||j==2*w)
                {
                    if(j==0)  x=i/2+1,y=j/2+1;
                    else  x=i/2+1,y=j/2;
                    a.push((data){ x, y }); //另一个出口
                    d[x][y] = 1;
                }
            }
         }
         ok=3-ok;
    }

    int ans = bfs(); //多源bfs
    if(ans==0) printf("1");
    else printf("%d", ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值