NC208246 胖胖的牛牛 优先队列+bfs 或 拆点法

链接:https://ac.nowcoder.com/acm/problem/208246
来源:牛客网

题目描述

每逢佳节胖三斤,牛牛在过去的节日里长胖了,连拐弯都困难,甚至会卡在门上,所以他很讨厌拐弯。给你一个N*N(2≤N≤100)的方格中,‘x’表示障碍,‘.’表示没有障碍(可以走),牛牛可以从一个格子走到他相邻的四个格子,但是不能走出这些格子。问牛牛从A点到B点最少需要转90度的弯几次。



输入描述:

第一行一个整数:N,下面N 行,每行N 个字符,只出现字符:‘.’,‘x’,‘A’,‘B’;表示上面所说的矩阵格子,每个字符后有一个空格。

输出描述:

一个整数:最少转弯次数。如果不能到达,输出-1。
示例1

输入

复制
3
. x A
. . .
B x .

输出

复制
2

备注:

开始和结束时的方向任意。

 

分析

拆点法,每个点有四个起始方向,四个终值方向,直走 距离+0,转弯 距离 +0

优先队列 + bfs ,如果当前位置和上上个位置 的 x 和 y 坐标都不同,说明转弯了,距离+1。

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>

using namespace std;

typedef pair<int,int> PII;

const int N=1010,M=1e7+10;
char mp[N][N];
int h[M],ne[M],num[M],w[M];
int n,idx;
PII st,ed;

int dist[M],vis[M];

int dx[]={-1,0,1,0};
int dy[]={0,1,0,-1};

priority_queue<PII,vector<PII>,greater<>>qu;

void add(int a,int b,int c) {
    ne[idx]=h[a];
    num[idx]=b;
    w[idx]=c;
    h[a]=idx++;
}

int hash_(int a,int b,int c) {
    return c*n*n+(a-1)*n+b;
}

void dijkstra()
{
    memset(dist,0x3f,sizeof(dist));
    qu.push({0,M-2});
    dist[M-2]=0;
    while(qu.size())
    {
        PII t=qu.top();
        qu.pop();
        int distance=t.first;
        int yuandian=t.second;
        if(!vis[yuandian])
        {
            vis[yuandian]=true;
            for(int i=h[yuandian];i!=-1;i=ne[i])
            {
                int g=num[i];
                if(dist[g]>dist[yuandian]+w[i])
                {
                    dist[g]=dist[yuandian]+w[i];
                    qu.push({dist[g],g});
                }
            }
        }
    }
}

int main() {
    memset(h,-1,sizeof h);
    cin>>n;
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            cin>>mp[i][j];
            if(mp[i][j]=='A') st={i,j};
            else if(mp[i][j]=='B') ed={i,j};
        }
    }
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++) {
            if(mp[i][j]=='x') continue;
            for(int k=0;k<4;k++) {
                int a=hash_(i,j,k);
                int b=hash_(i,j,(k+1)%4);
                int c=hash_(i,j,(k+3)%4);
                add(a,c,1),add(a,b,1);
                int x=i+dx[k],y=j+dy[k];
                if(x>0&&x<=n&&y>0&&y<=n&&mp[x][y]!='x') add(a,hash_(x,y,k),0);
            }
        }
    }
    
    for(int i=0;i<4;i++) add(M-2,hash_(st.first,st.second,i),0);
    for(int i=0;i<4;i++) add(hash_(ed.first,ed.second,i),M-1,0);

    dijkstra();
    
    if(dist[M-1]!=0x3f3f3f3f) cout<<dist[M-1];
    else cout<<-1;
}

 

posted @ 2022-08-11 17:22  er007  阅读(38)  评论(0编辑  收藏  举报