【洛谷P2199】最后的迷宫【BFS】【DFS】

版权声明:若希望转载,在评论里直接说明即可,谢谢! https://blog.csdn.net/SSL_ZYC/article/details/82559754

题目大意:

题目链接:https://www.luogu.org/problemnew/show/P2199
给出一个图及起点和终点,只要到达终点所在行、列或对角线上且两点之间没有墙就算到达终点。求到达终点的最少步数。


思路:

这道题真的算是蓝题吗。。。
算是很裸的广搜了。
这道题和裸的广搜其实只有一个差别:只要到达终点所在行、列或对角线上且两点之间没有墙就算到达终点。也就是说,这道题有多个终点,到达任意一个即可。
那么就直接跑一边DFS,从原终点往8个方向跑,直到遇见墙为止。那么走到的点就都是成立的终点。
之后就从起点跑BFS。就完全是裸的了。
还有这道题说 100 % 的数据范围是 n × m 16384 ,所以如果是最坏情况就会有 n = 1 , m = 16384 ,那么开二维数组就会炸内存。所以要把二维数组压成一个一位数组。
有多组数据,所以时间复杂度为 O ( t n m )


代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

const int dx[]={0,1,-1,0,0,-1,-1,1,1};
const int dy[]={0,0,0,1,-1,-1,1,-1,1};
int n,m,sx,sy,tx,ty,head,tail,ans[20501],state[20501];
bool a[20501],map[20501],p[20501];
char c;

void dfs(int x,int y,int k)  //找终点
{
    if (map[(x-1)*m+y]==1) return;  //墙
    if (x<1||x>n||y<1||y>m) return;  //越界
    a[(x-1)*m+y]=1;  //标记为终点
    dfs(x+dx[k],y+dy[k],k);
}

void bfs()  //裸的广搜
{
    head=0;
    tail=1;
    state[1]=(sx-1)*m+sy;
    while (head<tail)
    {
        head++;
        for (int i=1;i<=4;i++)
        {
            tail++;
            int x=(state[head]-1)/m+1;  
            int y=state[head]-(x-1)*m;  //取出行和列
            x+=dx[i];
            y+=dy[i];  //移动
            if (x<1||x>n||y<1||y>m)  //越界
            {
                tail--;
                continue;
            }
            state[tail]=(x-1)*m+y;  //入队
            if (p[state[tail]]||map[state[tail]])   //来到过这个点或是墙
            {
                tail--;
                continue;
            }
            p[state[tail]]=1;
            ans[tail]=ans[head]+1;
            if (a[state[tail]])  //到达任意一个终点
            {
                printf("%d\n",ans[tail]);
                return;
            }
        }
    }
    printf("Poor Harry\n");  //无法到达
}

int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++)
     for (int j=1;j<=m;j++)
     {
        cin>>c;
        while (c=='\n'||c==' ') cin>>c;
        if (c=='X') map[(i-1)*m+j]=1;
     } 
    while (1)
    {
        scanf("%d%d%d%d",&tx,&ty,&sx,&sy);
        if (!tx&&!ty&&!sx&&!sy) break;
        memset(a,0,sizeof(a));
        memset(ans,0,sizeof(ans));
        memset(p,0,sizeof(p));
        a[(tx-1)*m+ty]=1;
        for (int i=1;i<=8;i++)
         dfs(tx,ty,i);
        if (a[(sx-1)*n+sy])   //特判,本来就在终点上
        {
            printf("0\n");
            continue;
        }
        bfs();
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/SSL_ZYC/article/details/82559754