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 ...
随机推荐
- Maven中央仓库地址大全,Maven中央仓库配置示例
< Maven 中央仓库地址大全 > 在上一篇文章中完成了 < Maven镜像地址大全 >,后来又花了时间又去收集并整理了关于 maven 远程仓库地址,并整理于此,关于 Ma ...
- Vue. 之 Element dialog 拖拽
Vue. 之 Element dialog 拖拽 默认情况下,在使用Element的Dialog模块时,弹出框是不能移动的,且 一旦点击遮罩层区域,弹框就会消失. 解决方案: 1 在 utils 中新 ...
- jsonp 请求报Uncaught SyntaxError: Unexpected token :
$(document).ready(function() { jQuery.ajax({ type: 'GET', url: 'http://wncrunners.com/admin/colors.j ...
- VirtualBox新建虚拟机常用配置
1.内存给到1G,不然无法进入图形界面进行分区配置及软件包选择.虚拟机存储记得放到D盘. 2.网络选择桥接模式以便SSH,初次登陆后配置/etc/sysconfig/network-scripts/i ...
- UVa-401 Palindromes回文词
虽然是水题,但是容易错.参照了紫书的代码可以写的很简洁.主要还是注意常量数组的使用,能让代码变得简单许多 #include <iostream> #include <cstdio&g ...
- 使用代码创建rabbitmq交换机和队列绑定
1.获取channel对象 2.声明(创建)对列 // 第一个参数,queueName:对列名称.数据类型:String// 第二个参数,durable:是否持久化, 队列的声明默认是存放到内存中的, ...
- bzoj 3231 [Sdoi2008]递归数列——矩阵乘法
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3231 矩阵乘法裸题. 1018是10^18.别忘了开long long. #include& ...
- HDU6200 mustedge mustedge mustedge
不用看题就知道这是和什么tarjan.缩点或桥一类有关的题. 谁让他取题目叫一个mustedge还连续写3次的(哦,似乎是因为那个比赛的题目都是这个画风) 必须的边 >必须要经过的边 > ...
- JavaScript中this的指向(转载)
转载自:http://www.cnblogs.com/dongcanliang/p/7054176.html 前言 this 指向问题是入坑前端必须了解知识点,现在迎来了ES6时代,因为箭头函数的出现 ...
- Connection reset问题,INFO: I/O exception (java.net.SocketException) caught when processing reques
困扰我多年的Connection reset问题 第一次出现:是thrift的python client去请求server,发现偶尔出现这个问题 第二次:接入第三方的api,去请求数据时,发现一个接入 ...