hdu1728 逃离迷宫(bfs限制拐弯次数)


http://acm.hdu.edu.cn/showproblem.php?pid=1728

题意:给你一张图,*代表墙,.代表路,给你起点终点坐标和限制的拐弯次数,求起点是否可以在拐弯次数内到达终点。


思路:经典的bfs。一般搜索题限制的是走的步数,而这题限制的是拐弯次数。按照我想的土办法,结构体里添加拐弯次数,每走一步判断是否拐弯,最后把能够到达终点的路线的拐弯次数统计下来求最小,看是否超过限制的拐弯次数。这样一方面内存多了不少,另外有了好多不必要的路,万一100x100中间没障碍物那路线数多的令人发指啊(最起码10000的几次方,不知道怎么算),必须剪枝,问题就来了,怎么减?统计拐弯次数求最小必须枚举所有的情况,剪个毛,那DP?对于这种路线问题我貌似只见过floyd还是最短路,行不通。想不到好的方案,所以参考了这位大牛。


别人的思路就是屌啊,既然是判断拐弯次数,那从起点开始索性把四个方向能走的路走到底,我们称之为1号十字(四个方向形象化),经过的节点全入队列。如果没有搜到,那么一号十字上的每个节点都可以在此基础(类似于树)上按出队顺序建立二号十字(也许不像十字,因为有边界和墙的限制,但本质还是十字,注意二号十字应该有多个),若还没有搜到,那么建立三号十字,如此往复。。每多一层十字,拐弯次数加一,由于是一层一层建立,所以一旦搜到即是最小拐弯数,直接比较即可。这样效率提高了非常多还不影响结果,根本思想感觉有点像树的层序遍历,但又不是,膜拜啊。


注意已经访问过的节点也能走,我们看下面这种情况。

hdu1728 逃离迷宫(bfs限制拐弯次数)_第1张图片

我们知道1号线是红线,2号线是蓝线,3号线是绿线(不止一条),4号线是粉线。起点(1,1)终点(5,4)。(注意本题中横纵坐标反的,这里我们还是按照直观的坐标来说明)。可以看到,3号线由于墙挡着所以到不了终点,所以才会有4号线在三号线的基础上建立,但是第四行已经访问过了,所以把访问过的点经过,才可到达终点。(这图中虽然访问过的也能访问,但是重合的线我还是按照线序号小的优先画出,直观一点)。由于一号线也算方向但不算拐弯次数,所以初始化为-1。


整体来说这思路还是非常精辟,所以写了这么多。图纯手绘,别太吐槽哈~


#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

typedef long long LL;

const int N = 105;
const int INF = 0x3f3f3f3f;

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

struct node
{
    int x, y, step;
};

bool check(int x, int y)
{
    if(x>=1 && x<=m && y>=1 && y<=n && G[x][y]!='*') return true;
    else return false;
}

void bfs(int x, int y)
{
    if(x==ex && y==ey)
    {
        printf("yes\n");
        return;
    }
    memset(vis, false, sizeof(vis));
    queueque;
    node s;
    s.x = x;
    s.y = y;
    s.step = -1;
    vis[x][y] = true;
    que.push(s);
    while(!que.empty())
    {
        node tmp = que.front();
        que.pop();
        for(int i = 0; i < 4; i++)
        {
            node tmp2;
            tmp2 = tmp;
            tmp2.x += dir[i][0];
            tmp2.y += dir[i][1];
            while(check(tmp2.x, tmp2.y))
            {
                if(!vis[tmp2.x][tmp2.y])
                {
                    vis[tmp2.x][tmp2.y] = true;
                    tmp2.step = tmp.step+1;
                    if(tmp2.x == ex && tmp2.y == ey && tmp2.step<=limit)
                    {
                        printf("yes\n");
                        return;
                    }
                    que.push(tmp2);
                }
                tmp2.x += dir[i][0];
                tmp2.y += dir[i][1];
            }
        }
    }
    printf("no\n");
    return;
}

int main()
{
  //  freopen("in.txt", "r", stdin);
    int t;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d%d", &m, &n);
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= n; j++)
            {
                cin >> G[i][j];
            }
        scanf("%d%d%d%d%d", &limit, &sy, &sx, &ey, &ex);
        bfs(sx, sy);
    }
    return 0;
}


你可能感兴趣的:(hdu,数据结构-各种搜索)