Codeforces Round #354 (Div. 2)676D. Theseus and labyrinth

题目链接:http://codeforces.com/contest/676/problem/D
题意:
给一个n*m的迷宫,每个格子有一个字符,代表有几个门和门的方向。每秒允许两种操作,1.移动到相对应的门都通的邻节点 2.原地不动,地图上的每个门都顺时针转90°
问你从起点到终点最短距离
思路:
暴搜就行了…
flag是代表转了几次
fun是为了找到当前结点原地图能走的门
如果原地图i方向能走,那么经过flag次旋转后i+flag方向就能走,因为我们的dir数组是顺时针的,所以flag=1就相当于dir[(i+1)%4]

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include<stack>
#include<string>
#include<vector>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x&(-x))
typedef long long LL;
const int maxn = 1005;
const int inf=(1<<28)-1;
char Map[maxn][maxn];
struct node
{
    int flag,x,y,step;
};
int dir[4][2]={0,1,1,0,0,-1,-1,0}; 
int n,m,end_x,end_y;
bool mark[maxn][maxn][4];
void go(int a,int b,int c,int d,bool* ok)
{
    ok[0]=a,ok[1]=b,ok[2]=c,ok[3]=d;
}
bool ok[4],ok1[4];
void fun(node cur,bool A[])
{
    //右 下 左 上 
    int x=cur.x,y=cur.y;
    if(Map[x][y]=='+') go(1,1,1,1,A);
    else if(Map[x][y]=='-') go(1,0,1,0,A);
    else if(Map[x][y]=='|') go(0,1,0,1,A);
    else if(Map[x][y]=='^') go(0,0,0,1,A);
    else if(Map[x][y]=='>') go(1,0,0,0,A);
    else if(Map[x][y]=='<') go(0,0,1,0,A);
    else if(Map[x][y]=='v') go(0,1,0,0,A);
    else if(Map[x][y]=='L') go(1,1,0,1,A);
    else if(Map[x][y]=='R') go(0,1,1,1,A);
    else if(Map[x][y]=='U') go(1,1,1,0,A);
    else if(Map[x][y]=='D') go(1,0,1,1,A);
    else if(Map[x][y]=='*') go(0,0,0,0,A);
}
void bfs(node cur)
{
    queue<node>q;
    mark[cur.x][cur.y][0]=true;
    q.push(cur);
    while(!q.empty())
    {
        cur=q.front();
        q.pop();
        fun(cur,ok);
        for(int i=0;i<4;++i)
        if(ok[i])
        {
            node next=cur;
            next.x+=dir[(i+next.flag)%4][0];
            next.y+=dir[(i+next.flag)%4][1];
            next.step++;
            if(next.x<0||next.y<0||next.x>=n||next.y>=m) continue;
            fun(next,ok1);
            if(!ok1[(i+2)%4]) continue;
            if(mark[next.x][next.y][next.flag]) continue;
            mark[next.x][next.y][next.flag]=true;
            if(next.x==end_x&&next.y==end_y)
            {
                printf("%d\n",next.step);
                return ;
            }
            q.push(next);
        }
        node next=cur;
        next.flag++;
        next.step++;
        next.flag%=4;
        if(mark[next.x][next.y][next.flag]) continue;
        mark[next.x][next.y][next.flag]=true;
        q.push(next);
    }
    printf("-1\n");
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;++i)
    scanf("%s",Map[i]);
    node cur;
    scanf("%d%d",&cur.x,&cur.y);
    cur.x--,cur.y--;
    scanf("%d%d",&end_x,&end_y);
    end_y--,end_x--;
    if(cur.x==end_x&&cur.y==end_y)
    {
        printf("0\n");
        return 0;
    }
    cur.flag=0;
    cur.step=0;
    bfs(cur);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值