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 ...
随机推荐
- mac上python3.x安装 图文详解
mac安装brew报错及解决办法 https://blog.csdn.net/zdp072/article/details/82563320 更改脚本中的资源链接,替换成中国科学技术大学的镜像 htt ...
- LA2238 Fixed Partition Memory Management
题目大意: m(m<=10)个内存区域,n(n<=50)个程序.找出一个方案来,使得平均结束时刻尽量小.题目保证有解. 同一个程序运行在不同大小的内存区域内,其运行时间不同.(注意,这里说 ...
- bzoj 1034 [ZJOI2008]泡泡堂BNB——贪心
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1034 原来觉得和 bzoj4977跳伞求生 有点像(虽然还没做). 所以对于a[ ]从小到大 ...
- JQuery--extend的使用
$.extend({a,b,c},{a,bd}); 里面的对象属性如果 存在就替换,如果不存在就添加 var loadData = function (order) { var obj = getPa ...
- java -cp ../../DESUtil/ Hello,用-cp指定classpath
运行hello.class 文件 怎么用 java +路径 就是不在class目录下运行 怎么做??? 我想要的是 java 直接去运行某个路径下的class文件 不想到它的目录那里再java hel ...
- 提升mysql服务器性能(分库、分片与监控)
原文:提升mysql服务器性能(分库.分片与监控) 版权声明:皆为本人原创,复制必究 https://blog.csdn.net/m493096871/article/details/90145515 ...
- centos 安装redis2.8.9
1没有安装gcc yum install gcc-c++ 2. 安装tcl yum install -y tcl 3.安装redis $ wget http://download.redis.io/r ...
- 【洛谷P1827】【USACO】 美国血统 American Heritage 由二叉树两个序列求第三个序列
P1827 美国血统 American Heritage 题目描述 农夫约翰非常认真地对待他的奶牛们的血统.然而他不是一个真正优秀的记帐员.他把他的奶牛 们的家谱作成二叉树,并且把二叉树以更线性的&q ...
- 支付宝 python alipay 集成(转)
即时到帐只是支付宝众多商家服务中的一个,表示客户付款,客户用支付宝付款,支付宝收到款项后,马上通知你,并且此笔款项与交易脱离关系,商家可以马上使用. 即时到帐只对企业客户服务,注册成功企业账号以后,申 ...
- arcgis点密度专题
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...