uva 816 带方向的bfs

题意:

以下摘自小紫:

给一个9*9的迷宫,输入起点、离开起点时的朝向和终点,求一条最短路。(多解任意输出)

进入一个交叉点的方向(用NEWS这4个字母分别表示北东西南,即上右左下)不同,允许出去的方向也不同。

如图:


解析:

首先弄懂在每个点的状态有哪些:位置(x,y)朝向d,以此来建立节点,并且以此来建立bfs的状态step;

然后是方向dir与转弯turn的转换;

接着就bfs,然后打印路径,为了防止栈溢出,改用了循环,vector来保存路径;

有点坑爹的地方是判断外界要用[1,9],而我开始的时候直接判最大的输入了。


代码:

#pragma comment(linker, "/STACK:1677721600")
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
#include <cassert>
#include <iostream>
#include <algorithm>
#define pb push_back
#define mp make_pair
#define LL long long
#define lson lo,mi,rt<<1
#define rson mi+1,hi,rt<<1|1
#define Min(a,b) ((a)<(b)?(a):(b))
#define Max(a,b) ((a)>(b)?(a):(b))
#define mem(a,b) memset(a,b,sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)
#define rep(i,a,b) for(int i=(a); i<=(b); i++)
#define dec(i,a,b) for(int i=(a); i>=(b); i--)

using namespace std;
const int mod = 1e9 + 7;
const double eps = 1e-8;
const double ee = exp(1.0);
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);

int readT()
{
    char c;
    int ret = 0,flg = 0;
    while(c = getchar(), (c < '0' || c > '9') && c != '-');
    if(c == '-') flg = 1; else ret = c ^ 48;
    while( c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c ^ 48);
    return flg ? - ret : ret;
}

LL readTL()
{
    char c;
    int flg = 0;
    LL ret = 0;
    while(c = getchar(), (c < '0' || c > '9') && c != '-');
    if(c == '-') flg = 1; else ret = c ^ 48;
    while( c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c ^ 48);
    return flg ? - ret : ret;
}

const int maxX = 9 + 10;
const int maxY = 9 + 10;
const int maxD = 4 + 10;
const int maxT = 3 + 10;

int dir[][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
struct Node
{
    int x, y, d;
    Node(int _x = 0, int _y = 0, int _d = 0)
    {
        x = _x;
        y = _y;
        d = _d;
    }
};

bool maze[maxX][maxY][maxD][maxT];
int step[maxX][maxY][maxD];
Node path[maxX][maxY][maxD];

int getDir(char c)
{
    if (c == 'N')
        return 0;
    if (c == 'E')
        return 1;
    if (c == 'S')
        return 2;
    if (c == 'W')
        return 3;
}

int getTurn(char c)
{
    if (c == 'F')
        return 0;
    if (c == 'L')
        return 1;
    if (c == 'R')
        return 2;
}

Node go(Node u, int turn)
{
    int d = u.d;
    if (turn == 1)
        d = (d + 3) % 4;
    if (turn == 2)
        d = (d + 1) % 4;
    return Node(u.x + dir[d][0], u.y + dir[d][1], d);
}

bool inMaze(int x, int y)
{
    if (1 <= x && x <= 9 && 1 <= y && y <= 9)
        return true;
    return false;
}

void printPath(Node now)
{
    vector<Node> nodes;
    while (true)
    {
        nodes.pb(now);
        if (step[now.x][now.y][now.d] == 0)
            break;
        now = path[now.x][now.y][now.d];
    }
    nodes.pb(Node(now.x - dir[now.d][0], now.y - dir[now.d][1], now.d));

    int cnt = 0;
    for (int i = nodes.size() - 1; i >= 0; i--)
    {
        if (cnt % 10 == 0)
            printf(" ");
        printf(" (%d,%d)", nodes[i].x, nodes[i].y);
        if (++cnt % 10 == 0)
            puts("");
    }
    if (nodes.size() % 10 != 0)
        puts("");
}

bool bfs(Node st, Node ed)
{
//    cout << st.x << " " << st.y << " " << st.d << endl;

    st.x = st.x + dir[st.d][0];
    st.y = st.y + dir[st.d][1];

    mem(step, -1);
    step[st.x][st.y][st.d] = 0;

//    cout << st.x << " " << st.y << " " << st.d << endl;

    queue<Node> q;
    q.push(st);
    while (!q.empty())
    {
        Node now = q.front();
        q.pop();
        if (now.x == ed.x && now.y == ed.y)
        {
             printPath(now);
//            cout << "ok" << endl;
            return true;
        }
        for (int i = 0; i < 3; i++)
        {
            Node nxt = go(now, i);
            if (inMaze(nxt.x, nxt.y) && maze[now.x][now.y][now.d][i] && step[nxt.x][nxt.y][nxt.d] == -1)
            {
                step[nxt.x][nxt.y][nxt.d] = step[now.x][now.y][now.d] + 1;
                path[nxt.x][nxt.y][nxt.d] = now;
                q.push(nxt);
            }
        }
    }
    return false;
}

int main()
{
    #ifdef LOCAL
    FIN;
    #endif // LOCAL
    string name;
    string eof = "END";
    while (cin >> name)
    {
        if (name == eof)
            break;

        mem(maze, false);

        int stX = readT();
        int stY = readT();

        char c[2];
        scanf("%s", c);

        int edX = readT();
        int edY = readT();

//    cout << stX << " " << stY << endl;
//    cout << edX << " " << edY << endl;

        int x, y;
        string mapDir;
        while (scanf("%d", &x) && x)
        {
            scanf("%d", &y);
            while (cin >> mapDir)
            {
                if (mapDir == "*")
                    break;
                int len = mapDir.length();
                int d = getDir(mapDir[0]);
                for (int i = 1; i < len; i++)
                {
                    int t = getTurn(mapDir[i]);
                    maze[x][y][d][t] = true;
//                    cout << "x: " << x << "  y: " << y << "  d: " << d << "  t: " << t << endl;
                }
            }
        }

        cout << name << endl;
        bool ok = bfs(Node(stX, stY, getDir(c[0])), Node(edX, edY, 0));
        if (!ok)
        {
            puts("  No Solution Possible");
        }
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值