您的位置:首页 > 其它

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

2016-10-23 13:13 357 查看
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

;
bool vis

;
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  hdu