hdu 1728 逃离迷宫 BFS加优先队列 DFS()
http://acm.hdu.edu.cn/showproblem.php?pid=1728
题意就是能否在规定的转弯次数内从起点走到终点。刚走时那步方向不算。
只会bfs(),但想到这题需要记录转弯次数,所以就想在建立的节点内部添加一个变量记录本次走的方向,然后和上次走的方向比较,不同就增加转弯次数。就这样,按照bfs一层一层扩展,为了将转弯次数少的先扩展,就想到采用优先队列。但是按照这种思路写出来的代码WA。
后来看到网上有人倒着记录最小转弯次数(blog),也是采用的优先队列。虽然不知道作者为什么要倒着来,但我尝试这用这种写法正着来,这样也能过。
参考代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct pos
{
int x, y,ori;
};
pos dir[] = { {,,},{,,},{-,,},{,-,} };//四个方向偏移数组,第三维是代表这个方向的。
struct Node
{
int x, y, cnt,dir;//cnt记录转弯次数
bool operator < (const Node& rhs)const { //由于要是cnt小的先出队列,所以重载<
return cnt > rhs.cnt;
}
};
priority_queue<Node> que;
int k, m, n, sx, sy, ex, ey;
bool flag;
int ans[][];//记录起点到能到达每个点时的最小转弯次数。
char map[][];
char s[]; bool in(int a, int b)
{
if (a >= && a <= m&&b >= && b <= n&&map[a][b] == '.') return true;
return false;
} void BFS()
{
while (!que.empty())
{
Node u, v;
u = que.top(); que.pop(); if (u.cnt > k) continue;//超过最大转弯次数就不用管了。 for (int i = ; i < ; i++)
{
v.x = u.x + dir[i].x;
v.y = u.y + dir[i].y;
v.cnt = u.cnt;
if (in(v.x, v.y))
{
v.dir = dir[i].ori;//现在结点的方向是dir[i].ori
if (u.dir != - && v.dir != u.dir) {
v.cnt = u.cnt + ;
}
if (ans[v.x][v.y] >=v.cnt) {//这里一定要有等号!
ans[v.x][v.y] = v.cnt;
que.push(v);
}
}
}
}
if (ans[ex][ey] <= k) flag = true;
} int main()
{
int T;
scanf("%d", &T);
while (T--)
{
scanf("%d%d", &m, &n);
for (int i = ; i <= m; i++)
{
scanf("%s", s);
for (int j = ; j < n; j++)
{
map[i][j + ] = s[j];
ans[i][j + ] = 1e8;
}
}
scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
flag = false;
while (!que.empty()) que.pop();
Node node;
node.x = sx, node.y = sy;
node.dir = -, node.cnt = ;
que.push(node);
BFS();
if (flag) printf("yes\n");
else printf("no\n");
}
}
1
我就是按照原作者的思路照猫画虎的正着写了一下。其实之前网上有人说bfs()优先队列写会错,我很疑惑为什么不行,自己写的的确过不了。现在想想也许可能是因为我之前扩展结点后设置了访问数组,访问过的就不再访问了。而上面代码的想法是用ans数组更新答案。并且让能更新的结点入队列!这样可能能保证只要能更新答案一个结点可以走多次。就像有人说的以前都是求最小步数,结点最多走一次,但求最小转弯数时就不一样了。不知道想法对不对>_<.
网上大部分bfs()的办法都是到一个结点一直走到头。(blog1 blog2 )这个想法的确很好。
参考代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct pos
{
int x, y;
};
pos dir[] = { { , },{ , },{ -, },{ ,- } };
struct Node
{
int x, y, cnt;
};
queue<Node> que;
int vis[][];
char map[][];
char tmps[];
int m, n, sx, sy, ex, ey, k; bool in(int a, int b)
{
if (a >= && a <= m&&b >= && b <= n&&map[a][b] == '.') return true;
return false;
} int bfs()
{
while (!que.empty())
{
Node u;
u = que.front(); que.pop(); if (u.x == ex&&u.y == ey&&u.cnt <= k) return ; Node v;
v.cnt = u.cnt + ;////因为前面搜完了一个方向,就肯定会拐弯,所以要+1,也因此起点的cnt初始化为-1;
for (int i = ; i<; i++)
{
v.x = u.x + dir[i].x;
v.y = u.y + dir[i].y;
while (in(v.x, v.y))
{
if (!vis[v.x][v.y])
{
que.push(v);
vis[v.x][v.y] = ;
}
v.x += dir[i].x;
v.y += dir[i].y;
}
}
}
return -;
} int main()
{
int t;
scanf("%d", &t);
while (t--)
{
memset(vis, , sizeof(vis));
scanf("%d%d", &m, &n);
for (int i = ; i <= m; i++)
{
scanf("%s", tmps);
for (int j = ; j<n; j++)
{
map[i][j + ] = tmps[j];
vis[i][j + ] = ;
}
}
scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex); while (!que.empty()) que.pop();
Node u;
u.x = sx, u.y = sy, u.cnt = -;
vis[u.x][u.y] = ;
que.push(u); int ans = -;
ans = bfs();
if (ans >= ) printf("yes\n");
else printf("no\n");
}
return ;
}
2
最后就是dfs()解法。我本来看这道题没有深搜思路的,但觉得只要是搜索题,基本上两种方法都应该能做。就大概看了一下深搜解法。
参考代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
struct pos
{
int x, y,ori;
};
pos dir[] = { { ,, },{ ,, },{ -,, },{ ,-, } };//同bfs();
int ans[][];
char map[][];
char tmps[];
bool flag;
int m, n, sx, sy, ex, ey, k; bool in(int a, int b)
{
if (a >= && a <= m&&b >= && b <= n&&map[a][b] == '.') return true;
return false;
} void dfs(int x, int y, int cnt, int direct)//搜索的坐标、转弯次数、方向
{
if (x == ex&&y == ey&&cnt <= k) {
flag = true;
return;
} for (int i = ; i < ; i++) {
int newx = x + dir[i].x;
int newy = y + dir[i].y;
if (in(newx, newy))
{
if (direct == - || direct == dir[i].ori)
{
ans[newx][newy] = cnt;
dfs(newx, newy, cnt, dir[i].ori);
if (flag) return;
}
else if(cnt<k&&ans[newx][newy]>cnt)
{
ans[newx][newy] = cnt + ;
dfs(newx, newy, cnt + , dir[i].ori);
if (flag) return;
}
}
} } int main()
{
int t;
scanf("%d", &t);
while (t--)
{
scanf("%d%d", &m, &n);
for (int i = ; i <= m; i++)
{
scanf("%s", tmps);
for (int j = ; j<n; j++)
{
map[i][j + ] = tmps[j];
ans[i][j + ] = 1e8;
}
}
scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
flag = false;
dfs(sx, sy, , -);//开始时方向为设为-1
if (flag) printf("yes\n");
else printf("no\n");
}
return ;
}
3
hdu 1728 逃离迷宫 BFS加优先队列 DFS()的更多相关文章
- hdu 1728 逃离迷宫 bfs记转向
题链:http://acm.hdu.edu.cn/showproblem.php?pid=1728 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others) Mem ...
- hdu 1728 逃离迷宫 bfs记步数
题链:http://acm.hdu.edu.cn/showproblem.php?pid=1728 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others) Mem ...
- hdu 1728 逃离迷宫 (BFS)
逃离迷宫 Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submissi ...
- HDU 1728 逃离迷宫 BFS题
题目描述:输入一个m*n的地图,地图上有两种点,一种是 . 表示这个点是空地,是可以走的,另一种是 * ,表示是墙,是不能走的,然后输入一个起点和一个终点,另外有一个k输入,现在要你确定能否在转k次弯 ...
- HDU 1728 逃离迷宫(DFS||BFS)
逃离迷宫 Problem Description 给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可 ...
- HDU 1728 逃离迷宫(DFS)
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1728 题目: 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others) ...
- hdu - 1728逃离迷宫 && hdu - 1175 连连看 (普通bfs)
http://acm.hdu.edu.cn/showproblem.php?pid=1728 这两道题花了一下午的时候调试,因为以前做过类似的题,但是判断方向的方法是错的,一直没发现啊,真无语. 每个 ...
- HDU 1728 逃离迷宫(DFS经典题,比赛手残写废题)
逃离迷宫 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- hdu 1728:逃离迷宫(DFS,剪枝)
逃离迷宫 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
随机推荐
- sql 书写顺序
SELECT select_list [ INTO new_table ] FROM table_source [ WHERE search_condition ] [ GROUP BY group_ ...
- BZOJ2982: combination Lucas模板
2982: combination Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 734 Solved: 437[Submit][Status][Di ...
- Leetcode199. Binary Tree Right Side View二叉树的右视图
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值. 示例: 输入: [1,2,3,null,5,null,4] 输出: [1, 3, 4] 解释: 先求深度,中 ...
- 基于PHP的一种Cache回调与自动触发技术
$s = microtime(true); for($i=0; $iaaa($array, $array, $array); $data = a::bbb($array, $array, $array ...
- bzoj 1050 [HAOI2006]旅行comf——kruscal
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1050 因为还有Impossible的情况,所以想到了kruscal.(?) 但好像不太行.然 ...
- tr的display属性出现td的colspan无效问题
http://www.aichengxu.com/other/9262680.htm 今天在做项目的时候发现用javascript控制 tr 的显示隐藏时,当把tr的显示由“display:none” ...
- 移植thinkPHP的dump()函数
由于公司的开发机没有开xdebug拓展,导致var_dump()在浏览器上看很不方便. 因此,加入从thinkphp搬过来的dump()函数. function dump($var, $echo=tr ...
- OSGi教程:Class Space Consistency
此教程基于OSGi Core Release 7 OSGi类空间的一致性 详细内容上面英文教程有详细解答 下面主要是一些个人见解,若有不当之处,欢迎指出: "Class space cons ...
- webpack 4.X 创建 react项目
1. 新建一个文件夹2. 运行 npm init -y 快速初始化项目3. 在跟目录创建src文件夹 dist文件夹4. 在src下创建 index.html main.js // index.htm ...
- Djangog写XXOO管理的要求以及思路