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 ...
随机推荐
- [转载] 使用C/C++语言编写基于DSP程序的注意事项
原文地址:『转』使用C/C++语言编写基于DSP程序的注意事项作者:skysmile 1.不影响执行速度的情况下,可以使用c或c/c++语言提供的函数库,也可以自己设计函数,这样更易于使用“裁缝师 ...
- jquery同级遍历
siblings() 返回被选元素的所有同胞元素. next() 返回被选元素的下一个同胞元素. nextAll() 方法返回被选元素的所有跟随的同胞元素. nextUntil() 方法返回介于两个给 ...
- qq邮箱html邮件,图片不显示的问题
测试无论是站外的图片还是站内的图片,qq邮箱都会过滤图片,导致显示不出来. 解决办法:图片base64编码.效果图: 代码: <div class="container"&g ...
- 请问Pycharm如何实现变量的批量重命名?
1.点击你要改的单词,右键refactor ->rename 2. Ctrl + R 替换 Ctrl + Shift + F 全局查找 Ctrl + Shift + R 全局替换
- C# EventWaitHandle用法
waithander就是用来阻塞当前线程的,然后通过set()方法放开 namespace waithandler { class Program { //static EventWaitHandle ...
- solr高亮及摘要
修改了原文的一点内容:原文地址为:http://www.cnblogs.com/rainbowzc/p/3680343.html 高亮显示 两种方法: 1.在程序里通过设置query返回高亮信息 pu ...
- 你应该知道的25个非常有用的CSS技巧
在我们的前端CSS编码当中,经常要设置特殊的字体效果,边框圆角等等,还要考虑兼容性的问题, CSS网页布局,说难,其实很简单. 说它容易,往往有很多问题困扰着新手,在中介绍了非常多的技巧,这些小技巧与 ...
- drf作业01
api\urls from django.conf.urls import url from . import views urlpatterns = [ url(r'^cars/$',views.C ...
- c#的DateTime的各种字符串格式
今天看到工程里有关DateTime的有关知识,之前了解一些用法,比如怎么获取年月日,当前系统时间等等,但是,感觉还是有好多不知道,于是上网搜罗了一下,找到很多有关知识,现在与大家分享下: Da ...
- Python学习(一) 安装,环境搭建,IDE
第一篇废话太多了,我的博客最主要的是给自己看的,大家觉得还凑合也可以看看,能说自己想法的就更好了,因为一个人的思想是有局限性的.集思广益,自己的认知才不会被禁锢. 注:其他的系统没装,在Windows ...