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

来源:互联网 发布:thinkphp企业网站源码 编辑:程序博客网 时间:2024/04/28 20:24


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

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


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


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


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


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


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


#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>#include <queue>#include <stack>#include <ctype.h>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));    queue<node>que;    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;}


0 0