给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越,有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是,gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时,gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗?

Input  第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中, 
  第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地,字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x 1, y 1, x 2, y 2 (1 ≤ k ≤ 10, 1 ≤ x1, x 2 ≤ n, 1 ≤ y 1, y 2 ≤ m),其中k表示gloria最多能转的弯数,(x 1, y 1), (x 2, y2)表示两个位置,其中x 1,x 2对应列,y 1, y 2对应行。 
Output  每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。Sample Input

2
5 5
...**
*.**.
.....
.....
*....
1 1 1 1 3
5 5
...**
*.**.
.....
.....
*....
2 1 1 1 3

Sample Output

no
yes 分析:简单的BFS搜索最短路径,加上一个转弯的限制,就在判重的时候多加一个条件即可,但是直接判断是否访问过会造成漏解,剪枝条件应为:在该点的朝向的剩余转向次数
是否大于等于该点已经访问(未访问)过的(等于是为了防止0转向次数被剪掉),相当于转弯次数为优先级,越多其对解的贡献越大。
代码如下:
const int maxm = ;
const int dx[] = {-, , , };
const int dy[] = {, , -, }; struct Node {
int x, y, turn, dire;
Node(int _x = , int _y = , int _turn = -,int _dire = -):x(_x), y(_y),turn(_turn),dire(_dire) {}
}; int T, m, n, sx, sy, ex, ey, k, d[maxm][maxm][];
string buf[maxm]; bool inside(int x,int y) {
return x >= && x < m && y >= && y < n;
} bool bfs() {
memset(d, -, sizeof(d));
queue<Node> q;
for (int i = ; i < ; ++i) {
q.push(Node(sx, sy, k, i));
d[sx][sy][i] = k;
}
while (!q.empty()){
Node p = q.front();
q.pop();
if(p.x == ex && p.y == ey)
return true;
for (int i = ; i < ; ++i) {
Node tmp = p;
tmp.x += dx[i], tmp.y += dy[i];
if(i == p.dire) {
if(inside(tmp.x, tmp.y) && buf[tmp.x][tmp.y] == '.' && d[tmp.x][tmp.y][i] <= p.turn) {
d[tmp.x][tmp.y][i] = p.turn;
q.push(tmp);
}
} else if (tmp.turn > ) {
tmp.turn--, tmp.dire = i;
if(inside(tmp.x, tmp.y) && buf[tmp.x][tmp.y] == '.' && d[tmp.x][tmp.y][i] <= p.turn) {
d[tmp.x][tmp.y][i] = p.turn;
q.push(tmp);
}
}
}
}
return false;
} int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d", &m, &n);
for (int i = ; i < m; ++i)
cin >> buf[i];
scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
sy--, sx--, ey--, ex--;
if(bfs())
printf("yes\n");
else
printf("no\n");
}
return ;
}

 虽然我们用转向次数大于等于的判断条件来使0转向次数不被剪掉,但也加入了许多重复的点,我们可以继续优化代码,既然转向后次数减少,那么对解的贡献也减小,到达相同的点相同的方向的优先级一定小于不转弯的,那么,我们可以做出如下策略:如果不转弯,直接将前进后的入队,如果转弯,只转弯不前进入队,这样,转弯的情况就比直走慢了一步,自然就会有优先级上的差别,直接上代码进行体会:

const int maxm = ;
const int dx[] = {-, , , };
const int dy[] = {, , -, }; struct Node {
int x, y, turn, dire;
Node(int _x = , int _y = , int _turn = -,int _dire = -):x(_x), y(_y),turn(_turn),dire(_dire) {}
}; int T, m, n, sx, sy, ex, ey, k, d[maxm][maxm][];
string buf[maxm]; bool inside(int x,int y) {
return x >= && x < m && y >= && y < n;
} bool bfs() {
memset(d, , sizeof(d));
queue<Node> q;
for (int i = ; i < ; ++i) {
q.push(Node(sx, sy, k, i));
d[sx][sy][i] = k;
}
while (!q.empty()){
Node p = q.front();
q.pop();
if(p.x == ex && p.y == ey)
return true;
for (int i = ; i < ; ++i) {
Node tmp = p;
if(i == p.dire) {
tmp.x += dx[i], tmp.y += dy[i];
if(inside(tmp.x, tmp.y) && buf[tmp.x][tmp.y] == '.' && !d[tmp.x][tmp.y][i]) {
d[tmp.x][tmp.y][i] = ;
q.push(tmp);
}
} else if (tmp.turn > ) {
tmp.turn--, tmp.dire = i;
if(!d[tmp.x][tmp.y][i]) {
d[tmp.x][tmp.y][i] = ;
q.push(tmp);
}
}
}
}
return false;
} int main() {
scanf("%d", &T);
while(T--) {
scanf("%d%d", &m, &n);
for (int i = ; i < m; ++i)
cin >> buf[i];
scanf("%d%d%d%d%d", &k, &sy, &sx, &ey, &ex);
sy--, sx--, ey--, ex--;
if(bfs())
printf("yes\n");
else
printf("no\n");
}
return ;
}

从110ms降到了60ms,代码上只进行了基础微调。

 

Day2-J-逃离迷宫-HDU-1728的更多相关文章

  1. 逃离迷宫 HDU - 1728(bfs)

    逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  2. hdu - 1728逃离迷宫 && hdu - 1175 连连看 (普通bfs)

    http://acm.hdu.edu.cn/showproblem.php?pid=1728 这两道题花了一下午的时候调试,因为以前做过类似的题,但是判断方向的方法是错的,一直没发现啊,真无语. 每个 ...

  3. HDU 1728 逃离迷宫(DFS)

    题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1728 题目: 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)  ...

  4. HDU 1728 逃离迷宫(DFS经典题,比赛手残写废题)

    逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  5. HDU 1728:逃离迷宫(BFS)

    http://acm.hdu.edu.cn/showproblem.php?pid=1728 逃离迷宫 Problem Description   给定一个m × n (m行, n列)的迷宫,迷宫中有 ...

  6. hdu 1728 逃离迷宫 bfs记转向

    题链:http://acm.hdu.edu.cn/showproblem.php?pid=1728 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Mem ...

  7. hdu 1728 逃离迷宫 [ dfs ]

    传送门 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

  8. hdu 1728 逃离迷宫 bfs记步数

    题链:http://acm.hdu.edu.cn/showproblem.php?pid=1728 逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Mem ...

  9. hdu 1728:逃离迷宫(DFS,剪枝)

    逃离迷宫 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  10. HDU 1728 逃离迷宫

    [题目描述 - Problem Description] 给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,glo ...

随机推荐

  1. Spring Boot 使用 Dom4j XStream 操作 Xml

    Xml 现在仍然占据着比较重要的地位,比如微信接口中使用了 Xml 进行消息的定义.本章重点讨论 Xml 的新建.编辑.查找.转化,可以这么理解,本章是使用了 dom4j.xstream 也是在开发者 ...

  2. DOCK-SWARM

    服务原理: 创建集群:建立ingress网络,网关xxxxx.xxx.xxx.1 管理节点:docker swarm init --advertise-addr 192.168.4.119 工作节点: ...

  3. 的aspnet_client文件夹

    在早期,有一些asp.net组件是默认要调用(从客户端调用)服务器根(域名)下这个子目录里边的文件的. 不过如果你使用高版本的asp.net,那么全都从你的网站里调用了,因为asp.net有了更好地直 ...

  4. 解决github访问慢和下载项目慢的问题

    一.国内访问 GitHub 为什么很慢?  GitHub的CDN域名遭到DNS污染,导致无法连接使用 GitHub 的加速分发服务器,才使得国内访问速度很慢. 二.如何解决 DNS 污染?  通过修改 ...

  5. leetCode练题——12. Integer to Roman

    1.题目 12. Integer to Roman Roman numerals are represented by seven different symbols: I, V, X, L, C,  ...

  6. 【摘录自MDN】对事件冒泡和捕捉的解释

    当一个事件触发了一个有父元素的元素(例如我们的<video>时),现代浏览器运行两个不同的阶段 - 捕获阶段和冒泡阶段. 在捕获阶段: 浏览器检查元素的最外层祖先(<html> ...

  7. HHR计划---作业复盘-直播第三课

    一,出租车广告: 1,三个点不合格:周期太长了,大而全互联网产品,不符合MVP原则:业务关键点丢掉了:没有业务认知和成长. 2,关键假设: (1)车主有没有需求呀,画像怎么样? (2)车主收入如何,能 ...

  8. 1.WEB安全概述

    一.WEB常见的安全性问题简介 XSS(Cross-Site Scripting):跨站脚本攻击漏洞 CSRF(Cross-site request forgery):跨站请求伪造 文件上传漏洞 SQ ...

  9. python爬虫(二) urlparse和urlsplit函数

    urlparse和urlsplit函数: urlparse: url='http://www.baidu.com/s?wd=python&username=abc#1' result=pars ...

  10. C++启动和关闭外部exe

    转载:https://www.cnblogs.com/Sketch-liu/p/7277130.html 1.WinExec(  lpCmdLine: LPCSTR; {文件名和参数; 如没指定路径会 ...