HDU 1728 逃离迷宫 BFS题
题目描述:输入一个m*n的地图,地图上有两种点,一种是 . 表示这个点是空地,是可以走的,另一种是 * ,表示是墙,是不能走的,然后输入一个起点和一个终点,另外有一个k输入,现在要你确定能否在转k次弯之前从起点到达终点。
解题报告:首先说下这题坑的地方,就是输入起点和终点的坐标的时候,不是按照x1,y1,x2,y2输入的,而是按照y1,x1,y2,x2的顺序输入的。这题搞了很久 ,就是一开始没有想到怎么解决得到最小转弯次数的方法,一开始试过重复访问点,但是这样超内存了,然后如果不重复访问的话又会得不到转弯次数最小的点,就是说假如一个点从一条路线上被更新过的话,下一次从另一条路线上就不能再一次更新了,即使如果按照第二次走的路线转弯的次数会更少的 话。看了别人解题报告才想到,可以这样来解决就是当走到一个点时,如果可以沿着这条线直走的话,就一直走下去,除非到了边界,或者碰到墙,同时是否将这点放入队列的话也要做出相应的 改变,因为走的时候只要不是墙都能走,但是 不能把所有的点都放进队列,所以我们可以将从没有走过并且是可以走的点放进队列,而把已经走过的点不放进队列,这样就可以解决超内存的问题了,另外,走完当前这个点之后,不要忘了把这个点标记为已经走过。并且每次走之前判断是否已经到达了终点、边界,墙。一开始用自己写的队列发现代码更长,时间也更长,后来改用deque双端队列来写,首先代码只写了5分钟,而且没有调试一次就AC了,并且时间更短,内存更小,代码也更短。这里把我手动写的队列的和用deque的代码都附上。
手写队列代码:
#include<cstdio>
#include<cstring>
#include<time.h>
const int MAX = +;
int T,m,n,k,x1,y1,x2,y2;
int xx[] = {-,,,}; //定义移动方向
int yy[] = {,,,-};
int map[MAX][MAX];
typedef struct node {
int x,y,dire,time; //dire用来保存当前的方向,time表示走到当前步为止,转弯的次数
node() {
dire = time = ;
}
node *next;
}*LinkList,linklist;
bool bfs() {
LinkList head = NULL,p = NULL,temp;
head = new linklist; //新建队列头结点,头结点不放元素
p = new linklist; //便于存取节点
p->next = NULL;
p->x = x1,p->y =y1; //首先将起点加到队尾
head->next = p;
while(head->next!=NULL) {
temp = head->next; //将节点从队首取出
if(temp->x ==x2 && temp->y==y2 && temp->time-<k)
return true; //判断是否已经到达终点
for(int i = ;i<;++i) { //从当前的位置向周围四个方向走
int xxx = temp->x + xx[i];
int yyy = temp->y + yy[i];
if(xxx<||xxx>m||yyy<||yyy>n)
continue;
while(map[xxx][yyy]==||map[xxx][yyy]==) { //这一步很重要,如果当前走的方向是直的,且可走,则一直走到底,
//但只有从没有走过的点才加入到队列中
if(xxx<||xxx>m||yyy<||yyy>n)
break;
if(xxx ==x2 && yyy==y2 && temp->time-<k)
return true; LinkList q = new linklist;
q->next = NULL;
q->x = xxx;
q->y = yyy;
q->dire = i+;
q->time = temp->time;
if(temp->dire != q->dire)
q->time++;
if(!map[xxx][yyy]) { //从没走过的点才加入到队列中
q->next = p->next;
p->next = q;
p = p->next;
}
else delete q; //否则删除新建的这个点
map[xxx][yyy] = ; //走过之后标记为已走过,这一顺序,这句不能放前面
yyy+=yy[i];
xxx+=xx[i];
}
}
head->next = temp->next;
delete temp;
}
return false;
} int main() {
char d;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&m,&n);
memset(map,,sizeof(map));
for(int i = ;i<=m;++i) {
getchar();
for(int j = ;j<=n;++j) {
scanf("%c",&d);
if(d == '*')
map[i][j] = ;
}
}
scanf("%d%d%d%d%d",&k,&y1,&x1,&y2,&x2);
printf(bfs()? "yes\n":"no\n");
}
return ;
}
deque代码:
#include<cstdio>
#include<deque>
#include<iostream>
#include<cstring>
using namespace std;
const int MAX = +;
int k,x1,y1,x2,y2,m,n;
int xx[] = {-,,,};
int yy[] = {,,,-};
class node {
public:
int map[MAX][MAX];
bool bfs();
private:
struct Linklist {
int x,y,dire,times;
Linklist() {
dire = times = ;
}
};
};
bool node::bfs() {
deque<Linklist> head;
Linklist p;
p.x = x1,p.y = y1;
head.push_back(p);
deque<Linklist>::iterator iter;
while(head.size()!=) {
iter = head.begin();
for(int i = ;i<;++i) {
int xxx = iter->x + xx[i];
int yyy = iter->y + yy[i];
if(xxx<||xxx>m||yyy<||yyy>n)
continue;
while(map[xxx][yyy]!=) {
if(xxx == x2 && yyy ==y2 && iter->times-<k)
return true;
Linklist q;
q.x = xxx,q.y = yyy;
q.dire = i+;
q.times = iter->times;
if(q.dire != iter->dire)
q.times++;
if(map[xxx][yyy]==)
head.push_back(q);
map[xxx][yyy] = ;
xxx += xx[i];
yyy += yy[i];
if(xxx<||xxx>m||yyy<||yyy>n)
break;
}
}
head.pop_front();
}
return false;
}
int main() {
int T;
char c;
node temp;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&m,&n);
memset(temp.map,,sizeof(temp.map));
for(int i = ;i<=m;++i) {
getchar();
for(int j = ;j<=n;++j) {
scanf("%c",&c);
if(c == '*')
temp.map[i][j] = ;
}
}
scanf("%d%d%d%d%d",&k,&y1,&x1,&y2,&x2);
printf(temp.bfs()? "yes\n":"no\n");
}
return ;
}
HDU 1728 逃离迷宫 BFS题的更多相关文章
- 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加优先队列 DFS()
http://acm.hdu.edu.cn/showproblem.php?pid=1728 题意就是能否在规定的转弯次数内从起点走到终点.刚走时那步方向不算. 只会bfs(),但想到这题需要记录转弯 ...
- HDU 1728 逃离迷宫(DFS经典题,比赛手残写废题)
逃离迷宫 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 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 逃离迷宫
[题目描述 - Problem Description] 给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,glo ...
- hdu 1728:逃离迷宫(DFS,剪枝)
逃离迷宫 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
随机推荐
- SCRUM 12.16
今天大家又聚在一起开了个小会. 我们的爬虫出现了一些问题.某些美团的网页无法爬取,现在正在努力工作中. 关于用户统计的功能我们的以部分成员依然在完善中,17.18号应该基本能够推出. 成员 任务 彭林 ...
- Linux读书笔记第三、四章
第三章 主要内容: 进程和线程 进程的生命周期 进程的创建 进程的终止 1. 进程和线程 进程和线程是程序运行时状态,是动态变化的,进程和线程的管理操作(比如,创建,销毁等)都是有内核来实现的. Li ...
- 《Linux内核分析》-- 扒开系统调用的三层皮(下)之system_call中断处理过程 20135311傅冬菁
20135311傅冬菁 原创作品 <Linux内核分析>MOOC课程 分析system_call中断处理过程 内容分析与总结: 系统调用在内核代码中的工作机制和初始化 系统调用在用户态中 ...
- C与C++的编程风格区别
c和c++都是在实践中发展起来的语言.实用性极强.c是与UNIX/Linux的发展相辅相成的.而C++是B.S为了摆脱c与硬件以及底层过于紧密的苦恼,而开发的语言.C++可以说就是c语言的超集.任何c ...
- 更新pip10后 ImportError: cannot import name ‘main'
百度了几个回答都没有解决问题,有些回答明显是直接复制过来的一点价值都没有,然后google一下立马解决.很多时候不能怪搜索引擎,问题出在一些国内网友对知识的不负责任 解决:找到报错文件,也就是那个pi ...
- day3——关于<s:if/>和文件上传
一个小的注意点 <s:if test='#backyear==#yearatd'>selected="selected"</s:if> <s:if t ...
- SpringBoot 6.SpringBoot使用 Log4j2 实现日志输出
一.添加 Log4j2 的依赖 <!-- 引入 log4j2 必须排除 logging --> <dependency> <groupId>org.springfr ...
- Java 多线程初级汇总
多线程概述 抢占式多任务 直接中断而不需要事先和被中断程序协商 协作多任务 被中断程序同意交出控制权之后才能执行中断 多线程和多进程区别? 本质的区别在于每个进程有它自己的变量的完备集,线程则共享相同 ...
- lightgbm原理以及Python代码
原论文: http://papers.nips.cc/paper/6907-lightgbm-a-highly-efficient-gradient-boosting-decision-tree.pd ...
- codeforces71A
Way Too Long Words CodeForces - 71A XUPT_ACM的杨队是一个强迫症晚期的大神,他特别反感长单词,就像 "localization" 和&qu ...