HDU2364(三维数组表示方向)

题意是:不能回头,但是必须转弯;
难点就在如何表示方向还有如何处理转弯;

要把方向看成图的一个属性,并不一定要按照模拟过程走一遍。

开始突发奇想从终点开始搜,结果把自己搞晕了,还是贴从起点(’@’)开始搜的代码吧。

/**
 * hdu2364
 * 三维记忆bfs
 * 题目要求不能回头,但是可能转多个弯之后又回到走过的点,但还是有可能过去的,因为可能是从不同方向移动到这个点,
 * 所以,所以用一个三维的数组记录每一个点的状态,每个点有4种状态,即四个方向
 * 要把方向看成图的属性
 * ac
 */

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>

using namespace std;
#define INF 0x3f3f3f3f

char map[85][85];
bool visit[85][85][5];
int h, w;
int startx,starty;

struct node
{
    node(int _x = 0, int _y = 0, int _d = 0, int _cnt = 0):x(_x),y(_y),d(_d),cnt(_cnt){}
    int x;
    int y;
    int d;
    int cnt;//步数
};
node first;

int bfs()
{
    queue<node> Q;
    Q.push(first);

    int next[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    while(!Q.empty())
    {
        node temp = Q.front();
        Q.pop();

        if(temp.x == 1 || temp.x == h || temp.y == 1 || temp.y == w)
        {
            return temp.cnt;
        }

        for(int k = 0; k < 4; k++)
        {
            int nowx = temp.x + next[k][0];
            int nowy = temp.y + next[k][1];

            if(map[nowx][nowy] == '#' || visit[nowx][nowy][k])
            {
                continue;
            }
            if(nowx == startx && nowy == starty)
            {
                continue;
            }

            if(temp.d%2 == k%2)//k%2 == 0时上下,== 1时左右
            {
                //如果反向,啥也不做,相当于continue

                if(temp.d == k)
                {
                    if(k%2==0 && map[temp.x][temp.y+1] == '#' && map[temp.x][temp.y-1] == '#')
                    {
                        visit[nowx][nowy][k] = 1;
                        Q.push(node(nowx, nowy, k, temp.cnt+1));
                    }
                    if(k%2==1 && map[temp.x+1][temp.y] == '#' && map[temp.x-1][temp.y] == '#')
                    {
                        visit[nowx][nowy][k] = 1;
                        Q.push(node(nowx, nowy, k, temp.cnt+1));
                    }
                }
            }
            else
            {
                visit[nowx][nowy][k] = 1;
                Q.push(node(nowx, nowy, k, temp.cnt+1));
            }
        }
    }

    return -1;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(visit, 0, sizeof(visit));
        memset(map, 0, sizeof(map));

        scanf("%d%d", &h, &w);
        for (int i = 1; i <= h; i++)
        {
            getchar();
            for (int j = 1; j <= w; j++)
            {
                scanf("%c", &map[i][j]);

                if (map[i][j] == '@')
                {
                    startx = i;
                    starty = j;
                }
            }
        }

        first.x = startx; first.y = starty; first.d = -1; first.cnt = 0;
        int result = bfs();
        printf("%d\n", result);

    }
    return 0;
}

还有优先队列版本:

/**
 * hdu2364
 * 三维记忆bfs
 * 要把方向看成图的属性
 * ac
 */

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>

using namespace std;
#define INF 0x3f3f3f3f

char map[85][85];
bool visit[85][85][5];
int h, w;
int startx,starty;

struct node
{
    node(int _x = 0, int _y = 0, int _d = 0, int _cnt = 0):x(_x),y(_y),d(_d),cnt(_cnt){}
    int x;
    int y;
    int d;
    int cnt;
    friend bool operator < (const node &a,const node &b)
    {
        return a.cnt>b.cnt;
    }
};
node first;

int bfs()
{
    priority_queue<node> Q;
    Q.push(first);

    int next[4][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
    while(!Q.empty())
    {
        node temp = Q.top();
        Q.pop();

        if(temp.x == 1 || temp.x == h || temp.y == 1 || temp.y == w)
        {
            return temp.cnt;
        }

        for(int k = 0; k < 4; k++)
        {
            int nowx = temp.x + next[k][0];
            int nowy = temp.y + next[k][1];

            if(map[nowx][nowy] == '#' || visit[nowx][nowy][k])
            {
                continue;
            }
            if(nowx == startx && nowy == starty)
            {
                continue;
            }

            if(temp.d%2 == k%2)//k%2 == 0时上下,== 1时左右
            {
                //如果反向,啥也不做,相当于continue

                if(temp.d == k)
                {
                    if(k%2==0 && map[temp.x][temp.y+1] == '#' && map[temp.x][temp.y-1] == '#')
                    {
                        visit[nowx][nowy][k] = 1;
                        Q.push(node(nowx, nowy, k, temp.cnt+1));
                    }
                    if(k%2==1 && map[temp.x+1][temp.y] == '#' && map[temp.x-1][temp.y] == '#')
                    {
                        visit[nowx][nowy][k] = 1;
                        Q.push(node(nowx, nowy, k, temp.cnt+1));
                    }
                }
            }
            else
            {
                visit[nowx][nowy][k] = 1;
                Q.push(node(nowx, nowy, k, temp.cnt+1));
            }
        }
    }

    return -1;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(visit, 0, sizeof(visit));
        memset(map, 0, sizeof(map));

        scanf("%d%d", &h, &w);
        for (int i = 1; i <= h; i++)
        {
            getchar();
            for (int j = 1; j <= w; j++)
            {
                scanf("%c", &map[i][j]);

                if (map[i][j] == '@')
                {
                    startx = i;
                    starty = j;
                }
            }
        }

        first.x = startx; first.y = starty; first.d = -1; first.cnt = 0;
        int result = bfs();
        printf("%d\n", result);

    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值