Codeforces 676D Theseus and labyrinth(最短路)

题意:

给定一个迷宫,起点和终点,每一个可以走的格子上都有不同的门的情况,每次都可以选择到达周围符合条件的格子或者是让所有格子的门顺时针旋转一下,问你从起点到重点的最短距离。

解法:

因为每次都是转90度,所以对于每个格子来说,都有四个状态,所以建立一个分层图,每层都代表个点的一种状态,然后直接BFS即可。

代码:

//
//  Created by  CQU_CST_WuErli
//  Copyright (c) 2016 CQU_CST_WuErli. All rights reserved.
//
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <stack>
#include <set>
#include <algorithm>
#include <sstream>
#define CLR(x) memset(x,0,sizeof(x))
#define OFF(x) memset(x,-1,sizeof(x))
#define MEM(x,a) memset((x),(a),sizeof(x))
#define BUG cout << "I am here" << endl
#define lookln(x) cout << #x << "=" << x << endl
#define SI(a) scanf("%d", &a)
#define SII(a,b) scanf("%d%d", &a, &b)
#define SIII(a,b,c) scanf("%d%d%d", &a, &b, &c)
const int INF_INT=0x3f3f3f3f;
const long long INF_LL=0x7f7f7f7f;
const int MOD=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
typedef long long  ll;
using namespace std;

const int N = 1010;

int n, m;
int sx, sy, ex, ey;
char mp[N][N];
int dir[4][2] = {-1, 0, 0, 1, 1, 0, 0, -1};
int vis[N][N][4];
int ok[N][N][4];

struct P {
    int x, y, sta, dis;
    P(int a, int b, int c, int d): x(a), y(b), sta(c), dis(d){}
};

void init() {
    CLR(vis);
    CLR(ok);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; ++j) {
            if (mp[i][j] == '+') ok[i][j][0] = ok[i][j][1] = ok[i][j][2] = ok[i][j][3] = 1;
            else if (mp[i][j] == '-') ok[i][j][1] = ok[i][j][3] = 1;
            else if (mp[i][j] == '|') ok[i][j][0] = ok[i][j][2] = 1;
            else if (mp[i][j] == '^') ok[i][j][0] = 1;
            else if (mp[i][j] == '>') ok[i][j][1] = 1;
            else if (mp[i][j] == 'v') ok[i][j][2] = 1;
            else if (mp[i][j] == '<') ok[i][j][3] = 1;
            else if (mp[i][j] == 'L') ok[i][j][0] = ok[i][j][1] = ok[i][j][2] = 1;
            else if (mp[i][j] == 'R') ok[i][j][0] = ok[i][j][2] = ok[i][j][3] = 1;
            else if (mp[i][j] == 'U') ok[i][j][1] = ok[i][j][2] = ok[i][j][3] = 1;
            else if (mp[i][j] == 'D') ok[i][j][0] = ok[i][j][1] = ok[i][j][3] = 1;
        }
    }
}

int bfs() {
    queue<P> q;
    q.push(P(sx, sy, 0, 0));
    vis[sx][sy][0] = 1;
    while (q.size()) {
        P u = q.front(); q.pop();
        int x = u.x, y = u.y, dis = u.dis, sta = u.sta;
        if (x == ex && y == ey) {
            return dis;
        }
        if (!vis[x][y][(sta + 1) % 4]) {
            vis[x][y][(sta + 1) % 4] = 1;
            q.push(P(x, y, (sta + 1) % 4, dis + 1));
        }
        for (int i = 0; i < 4; i++) {
            if (ok[x][y][(i - sta + 4) % 4]) {
                int nx = x + dir[i][0], ny = y + dir[i][1];
                if (nx < 1 || nx > n || ny < 1 || ny > m) continue;
                if (ok[nx][ny][(i - sta + 6) % 4] && !vis[nx][ny][sta]) {
                    vis[nx][ny][sta] = 1;
                    q.push(P(nx, ny, sta, dis + 1));
                }
            }
        }
    }
    return -1;
}

int main(int argc, char const *argv[]) {
#ifdef LOCAL
    freopen("C:\\Users\\john\\Desktop\\in.txt","r",stdin);
    // freopen("C:\\Users\\john\\Desktop\\out.txt","w",stdout);
#endif
    while (SII(n, m) == 2) {
        for (int i = 1; i <= n; i++)
            scanf("%s", mp[i] + 1);
        init();
        SII(sx, sy);
        SII(ex, ey);
        cout << bfs() << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值