HDU1728逃离迷宫

给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?
Input
  第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中, 
  第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x  1, y  1, x  2, y  2 (1 ≤ k ≤ 10, 1 ≤ x 1, x  2 ≤ n, 1 ≤ y  1, y  2 ≤ m),其中k表示gloria最多能转的弯数,(x  1, y  1), (x  2, y 2)表示两个位置,其中x  1,x  2对应列,y  1, y  2对应行。 
Output
  每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。
Sample Input
2
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
5 5
...**
*.**.
.....
.....
*....
2 1 1 1 3
Sample Output
no

yes

刚开始我拿到这道题便看出来了这是一道很简(keng)单(die)的BFS的题目,这道题目的难点在于计算层数的时候不是以步数为单位的,是以转向的次数为单位。每转一次向,为1层,直到第二次转向才到下一层。所以转向后,一定要搜索到底!!!!!这才是关键。

下面放一下刚开始写的代码。

#include <iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
int dir[4][2]={0,1,1,0,0,-1,-1,0};//右、下、左、上
int k;
int m,n;
int x2,y2;
int top=0,p=0;
int w[101][101];
struct node
{
    int d;
    int x,y;//x是行,Y是列
};
struct node zhan[10010];
void BFS(int xi,int yi)
{
    if(xi==x2&&yi==y2)
    {
        printf("yes\n");
        return ;
    }
    for(int i=0;i<4;i++)
    {
        int x0=zhan[top].x,y0=zhan[top].y;
        if(w[zhan[top].x+dir[i][0]][zhan[top].y+dir[i][1]]==0)
        {
            while(w[x0+dir[i][0]][y0+dir[i][1]]==0)
            {
                p++;
                x0=x0+dir[i][0];
                y0=y0+dir[i][1];
                zhan[p].x=x0;
                zhan[p].y=y0;
                zhan[p].d=zhan[top].d+1;
                w[x0][y0]=2;
               // printf("   (%d,%d)   %d   %d\n",x0,y0,zhan[top].d,zhan[p].d);
                if(zhan[p].d>k)
                {
                    printf("no\n");
                    return ;}
                if(x0==x2&&y0==y2)
                {
                    //printf("yes,%d\n",zhan[p].d);
                    printf("yes\n");
                    return ;
                }
            }
        }
    }
    top++;
    BFS(zhan[top].x,zhan[top].y);
}
int main()
{

    int a;
    scanf("%d",&a);
    while(a--)
    {
        top=0,p=0;
        memset(w,1,sizeof(w));
        scanf("%d %d",&m,&n);
        int i,j;
        for(i=1;i<=m;i++)
        {
            getchar();
            for(j=1;j<=n;j++)
            {
                char c;
                scanf("%c",&c);
                if(c=='.') w[i][j]=0;
                else w[i][j]=1;
            }
        }
        int x1,y1;
        scanf("%d %d %d %d %d",&k,&y1,&x1,&y2,&x2);
        if(x2>m||y2>n||x2<1||y2<1||w[x2][y2]==1)
        {
            printf("no\n");
            return 0;
        }
        if(x1>m||y1>n||x1<1||y1<1||w[x1][y1]==1)
        {
            printf("no\n");
            return 0;
        }
        zhan[0].x=x1;
        zhan[0].y=y1;
        zhan[0].d=-1;
        w[x1][y1]=2;
        BFS(x1,y1);
    }
    return 0;
}

然后怎么提交都不对!!!为什么呢,因为忽略了一个很大的问题,就是中间BFS函数部分,输出yes的判断条件那里,因为他是按照转弯数搜索的,也就是说很可能有的点在这一层上但是是后来才转到这里的,是搜索完别的层数多的之后回溯会来的。所以中间会出现一段转弯数>要求的转弯数的情况,这时候这段代码会直接return出来,就没办法进行后面的搜索了。所以一直wrong answer。(其实这里我也有个小小的疑惑,为什么递归的时候退出来回到原来的函数就不行了呢)

然后改进了一下,对了。并且把递归改成了循环。

/*
1
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
5 5
...**
*.**.
.....
.....
*....
2 1 1 5 3
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
*/
#include <iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
int dir[4][2]={0,1,1,0,0,-1,-1,0};//右、下、左、上
int k;
int m,n;
int x2,y2;
int v[101][101];
char w[101][101];
struct node
{
    int d;
    int x,y;//x是行,Y是列
};
bool check(int x,int y)
{
    if(x >= 1 && y >= 1 && x <= m && y <= n && w[x][y] != '*')
        return 1;
    return 0;
}
struct node zhan[10010];
void BFS(int xi,int yi)
{
    int top=0,p=1;
    if(xi==x2&&yi==y2)
    {
        printf("yes\n");
        return ;
    }
    zhan[0].x=xi;
    zhan[0].y=yi;
    zhan[0].d=-1;
    v[xi][yi]=1;
    while(top!=p)
    {
    //printf("%d %d  (%d,%d)\n",top,p,zhan[p].x,zhan[p].y);
         for(int i=0;i<4;i++)
        {
            int x0=zhan[top].x+dir[i][0],y0=zhan[top].y+dir[i][1];
            while( check(x0,y0) )
            {
                if(v[x0][y0]==0)
                {
                    zhan[p].x=x0;
                    zhan[p].y=y0;
                    zhan[p].d=zhan[top].d+1;
                    v[x0][y0]=1;
                   // printf("(%d,%d)\n",x0,y0);
                    if(x0==x2&&y0==y2&&zhan[p].d<=k)
                    {
                        printf("yes\n");
                        return ;
                    }
                    p++;
                }
                x0=x0+dir[i][0];
                y0=y0+dir[i][1];
            }
        }
    top++;
    }
    printf("no\n");
    return ;
}
int main()
{

    int a;
    scanf("%d",&a);
    while(a--)
    {
        memset(v, 0, sizeof(v));
        memset(w, 0, sizeof(w));
        int top=0,p=0;
        memset(w,1,sizeof(w));
        scanf("%d %d",&m,&n);
        int i,j;
        for(i=1;i<=m;i++)
        {
            for(j=1;j<=n;j++)
            {
                scanf(" %c",&w[i][j]);
            }
        }
        int x1,y1;
        scanf("%d %d %d %d %d",&k,&y1,&x1,&y2,&x2);
        BFS(x1,y1);
    }
    return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值