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。
整体来说这思路还是非常精辟,所以写了这么多。图纯手绘,别太吐槽哈~
题意:给你一张图,*代表墙,.代表路,给你起点终点坐标和限制的拐弯次数,求起点是否可以在拐弯次数内到达终点。
思路:经典的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; }
相关文章推荐
- hdu1728 逃离迷宫 【bfs记录转向次数 2种】
- HDU1728-逃离迷宫-BFS
- HDU1728 逃离迷宫(BFS)
- hdoj 1728 逃离迷宫 【BFS 记录转弯次数】
- HDU1728 逃离迷宫【BFS】
- HDU 1728 逃离迷宫 转向限制BFS
- HDU1728 逃离迷宫 解题报告--bfs
- HDU1728:逃离迷宫(BFS)
- HDU1728 逃离迷宫 BFS
- hdu-1728逃离迷宫(dfs 求拐弯次数)
- HDU1728:逃离迷宫(BFS)
- HDOJ 1728 逃离迷宫(BFS + 记录拐弯次数)
- hdu1728 逃离迷宫--BFS
- (hdu step 4.2.7)逃离迷宫(在有转弯次数的限制的情况下,判断一个点是否能到另一个点)
- hdu1728 逃离迷宫( bfs + 标记转向次数)
- hdu1728 逃离迷宫 --bfs
- HDU1728:逃离迷宫【BFS】
- 【hdu 1728】 逃离迷宫 广搜(最少拐弯次数)
- hdu1728逃离迷宫 bfs
- hdu1728 逃离迷宫(bfs)