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 ...
随机推荐
- ES6学习笔记之Symbol
新的数据类型Symbol 1. 概述 ES5 的对象属性名都是字符串,这容易造成属性名的冲突.比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与 ...
- netbeans调试webapp 只能用localhost访问
etbeans 我的电脑是192.168.0.2,用这个地址访问 网上有人说,分两种情况 此问题分两种情况: 1. 可以用127.0.0.1访问 2. 不能用127.0.0.1访问 针对第一种情况,我 ...
- tomcat的三种部署项目的方式
1.直接将项目放在webapps目录下. 如果将项目直接打成WAR包,放在webapps目录下会自动解压 项目的文件夹名称就是项目的访问路径,也就是虚拟目录. 2.配置conf文件夹下的server. ...
- IO流3 --- File类的常用方法2 --- 技术搬运工(尚硅谷)
File类的判断功能 @Test public void test5(){ File file = new File("hello.txt"); //判断是否是文件目录 Syste ...
- 想真正了解JAVA设计模式看着一篇就够了。 详解+代码实例
Java 设计模式 设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结 设计模式分为 23 种经典的模式,根据用途我们又可以分为三大类.分别是创建型模式.结构型模式和行为型模式 列举几种设 ...
- Comparator进行List集合排序
对数据库中查询到的结果进行排序,一般开发中,实体类是没有实现Comparable接口的,所以不能实现compareTo()方法进行排序, 只能用Comparator去进行排序,只需要在带排序的集合中加 ...
- 简单描述如何安装配置一个apache开源版hadoop,只描述即可,无需列出完整步骤,能列出步骤更好
1 ) 安装JDK并配置环境变量(/etc/profile) 2) 关闭防火墙 3) 配置hosts文件,方便hadoop通过主机名访问(/etc/hosts) 4) 设置ssh免密码登录 5) 解压 ...
- 洛谷P1312 [NOIP2011提高组Day1T3]Mayan游戏
Mayan游戏 题目描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个 7 行5 列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.游 ...
- 洛谷P1890 gcd区间 [2017年6月计划 数论09]
P1890 gcd区间 题目描述 给定一行n个正整数a[1]..a[n]. m次询问,每次询问给定一个区间[L,R],输出a[L]..a[R]的最大公因数. 输入输出格式 输入格式: 第一行两个整数n ...
- 洛谷P1965 转圈游戏 [2013NOIP提高组 D1T1][2017年6月计划 数论04]
P1965 转圈游戏 题目描述 n 个小伙伴(编号从 0 到 n-1)围坐一圈玩游戏.按照顺时针方向给 n 个位置编号,从0 到 n-1.最初,第 0 号小伙伴在第 0 号位置,第 1 号小伙伴在第 ...