zoukankan      html  css  js  c++  java
  • 洛谷 P2199 最后的迷宫

    这道题作为一道广度优先搜索的题目,和其他的写法没有太大不同,但是有很多坑~,(多踩几次就填上了)

    1.在这道题中,哈利可以只要与奖杯在题目所描述的八个方向上能够直接通往奖杯(也就是说不能有墙),那么就可以结束搜索,次数也可以不用加一。

    2.这道题要重复输入多遍哈利和奖杯的坐标,而且是先输入奖杯,在输入哈利坐标(坑!),所以可以使用一个数组先记录下来,然后每一遍都进行初始化

    3.再就是奖杯一开始就在哈利的手中(奖杯坐标与哈利坐标重合),需要特判

    4.这道题不能只用一个数组来记录不能走到的点,因为如果在搜索的过程中只用一个数组进行记录,就会导致走过的点和本身是墙的点都变成一个不能走的点,但是在最后判断能否直接拿到的时候并不能考虑走过的点,所以需要用两个数组进行记录,一个记录墙壁,一个记录已走过的点,避免混乱

    源代码:

    #include<iostream>
    #include<cstdio>
    #include<math.h>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    
    struct STU
    {
        int xx;
        int yy;
    };
    
    queue<STU> q;
    int go[5][2]={{0,0},{1,0},{-1,0},{0,1},{0,-1}};
    int val[1600][1600];
    int mapp1[1600][1600];//记录墙壁坐标
    int mapp2[1600][1600];//记录已走点坐标
    int step[1600][1600];
    int flag,n,m,ex,ey,bx,by,tx,ty,qx,qy,ans;
    char a;
    
    int win(int x,int y)//判断可不可以用“飞来咒”直接拿到奖杯
    {
        if(x==ex&&y==ey)//奖杯和哈利重合
        {
            return 1;
        }    
        
        if(x==ex)//在同一水平直线上
        {    
            for(int i=min(y,ey);i<=max(y,ey);i++)
            {
                if(mapp1[x][i]==1) return 0;
            }
            
            return 1;
        }
        if(y==ey)//在同一竖直直线上
        {
            for(int i=min(x,ex);i<=max(x,ex);i++)
            {
                if(mapp1[i][y]==1) return 0;
                
            }
            return 1;
        }
        if(x-y==ex-ey)//在同一方向为东北——西南的直线上
        {
            for(int i=1;i<=abs(ex-x);i++)
            {
                if(x<ex)
                {
                    if(mapp1[x+i][y+i]==1) return 0;
                }
                else
                {
                    if(mapp1[x-i][y-i]==1) return 0;
                }
            }
            
            return 1;
        }    
        if(x+y==ex+ey)//在同一方向为西北——东南的直线上
        {
            for(int i=1;i<=abs(x-ex);i++)
            {
                if(x<ex)
                {
                    if(mapp1[x+i][y-i]==1) return 0;
                }
                else
                {
                    if(mapp1[x-i][y+i]==1) return 0;
                }
            }
            
            return 1;
        }
        
        return 0;//啥都不符合。。。
    }
    
    int bfs(int x,int y)//正常广度优先搜索
    {
        q.push((STU){x,y});
        mapp2[x][y]=1;
        step[x][y]=0;
        
        while(q.size()!=0)
        {
            qx=q.front().xx;
            qy=q.front().yy;
            q.pop();
            
            if(win(qx,qy)==1)//能拿到就结束
            {
                return step[qx][qy];
            }
            
            for(int i=1;i<=4;i++)
            {
                tx=qx+go[i][0];
                ty=qy+go[i][1];
                
                if(tx<1||ty<1||tx>n||ty>m||mapp2[tx][ty]==1)
                {
                    continue;
                }
                
                mapp2[tx][ty]=1;
                step[tx][ty]=step[qx][qy]+1;
                q.push((STU){tx,ty});
            }
        }
        
        return -1;//拿不到打个标记
    }
    
    int main(void)
    {
        scanf("%d%d",&n,&m);
        
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                cin>>a;
                
                if(a=='X') val[i][j]=1;//标记墙壁,之后每一遍输入均可使用
            }
        }
        
        for( ; ; )
        {
            scanf("%d%d%d%d",&ex,&ey,&bx,&by);
            
            if(bx==0&&by==0&&ex==0&&ey==0)
            {
                break;
            }
            
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    mapp2[i][j]=mapp1[i][j]=val[i][j];//走过的也把墙壁标记为已走路径,不再经过
                }
            }
            
            ans=bfs(bx,by);
            
            if(ans==-1)
            {
                printf("Poor Harry
    ");
            }
            else
            {
                printf("%d
    ",ans);
            }
            
            memset(step,0,sizeof(step));//切记初始化
            memset(mapp1,0,sizeof(mapp1));
            memset(mapp2,0,sizeof(mapp2));
            
            while(q.size()!=0)//队列初始化
            {
                q.pop();
            }
        }
        
        return 0;
    }
  • 相关阅读:
    spring boot 2.1学习笔记【五】SpringBootTest单元测试及日志
    Java网络编程-UDP
    Java网络编程-TCP
    String的特性
    内存池的使用
    软件定时器的使用
    邮箱
    事件集
    线程优先级翻转
    临界区,互斥量与信号量
  • 原文地址:https://www.cnblogs.com/jd1412/p/12905407.html
Copyright © 2011-2022 走看看