文章标题
来源:互联网 发布:万讯网络中控 编辑:程序博客网 时间:2024/06/06 12:36
BIT 程序设计与实践
21. 吃货续
题目
上次郭老师让大家帮忙找餐厅,今天他又来请大家帮忙了。郭老师想从自己的当前位置用最快的时间到达某一餐厅,他每次只能按照上、下、左、右四个方向移动,每次移动计为 1 个时间,但由于路况纷繁复杂,中间有很多的路障,导致他不得不绕过这些路障。此时,具有魔性的高老师出现了,他帮助郭老师在途中的某些点放置了穿梭机,任意两个穿梭机之间可以完成瞬间移动(瞬间移动不耗费时间)。
输入
第一行包含两个数字 n m(1 ≤ n, m ≤ 2000)
接下来包含 n 行,每行 m 个字符,表示现在的地图。’.’ 表示空地,’M’ 表示路障,’E’ 表示穿梭机,’N’ 表示郭老师当前所在的位置,’C’ 表示要找的餐厅。’N’ 和 ‘C’ 在地图中出现且仅出现一次。
输出
郭老师最快多长时间能到达餐厅。如果永远到不了,输出 “Not Happy”。
样例
输入:
6 6
…E..
EMM.M.
.M..M.
.MC.M.
.MMM..
N..E..
输入:
7
思路
有题可知明显是一个BFS广度优先搜索的题目;
首先想到的是c++的STL库里面的queue函数:
queue函数成员
C++队列Queue类成员函数如下:
back()返回最后一个元素
empty()如果队列空则返回真
front()返回第一个元素
pop()删除第一个元素
push()在末尾加入一个元素
size()返回队列中元素的个数
queue基本操作
queue入队,如例:q.push(x); 将x 接到队列的末端。
queue出队,如例:q.pop(); 弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问queue队首元素,如例:q.front(),即最早被压入队列的元素。
访问queue队尾元素,如例:q.back(),即最后被压入队列的元素。
判断queue队列空,如例:q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:q.size()
然而bit的网教编译器不支持STL库,这就很尴尬了!!!!
所以只能用
数组模拟队列
队列可以用数组Q[1…m]来存储,数组的上界m即是队列所容许的最大容量。在队列的运算中需设两个指针:head,队头指针,指向实际队头元素;tail,队尾指针,指向实际队尾元素的下一个位置。一般情况下,两个指针的初值设为0,这时队列为空,没有元素。数组定义Q[1…10]。Q(i) i=3,4,5,6,7,8。头指针head=2,尾指针tail=8。队列中拥有的元素个数为:L=tail-head。现要让排头的元素出队,则需将头指针加1。即head=head+1这时头指针向上移动一个位置,指向Q(3),表示Q(3)已出队。如果想让一个新元素入队,则需尾指针向上移动一个位置。即tail=tail+1这时Q(9)入队。当队尾已经处理在最上面时,即tail=10,如果还要执行入队操作,则要发生上溢,但实际上队列中还有三个空位置,所以这种溢出称为假溢出。
克服假溢出的方法有两种。一种是将队列中的所有元素均向低地址区移动,显然这种方法是很浪费时间的;另一种方法是将数组存储区看成是一个首尾相接的环形区域。当存放到n地址后,下一个地址就翻转为1。在结构上采用这种技巧来存储的队列称为循环队列。
队列和栈一样只允许在断点处插入和删除元素。
循环队的入队算法如下:
1、tail=tail+1;
2、若tail=n+1,则tail=1;
3、若head=tail,即尾指针与头指针重合了,表示元素已装满队列,则作上溢出错处理;
4、否则,Q(tail)=X,结束(X为新入出元素)。
队列和栈一样,有着非常广泛的应用。
注意:(1)有时候队列中还会设置表头结点,就是在队头的前面还有一个结点,这个结点的数据域为空,但是指针域指向队头元素。
(2)另外,上面的计算还可以利用下面给出的公式cq.rear=(cq.front+1)/max;
当有表头结点时,公式变为cq.rear=(cq.front+1)/(max+1)。
题目中的穿梭机是一个难点!
在输入数据的时候,开了一个数组将所有穿梭机的坐标存入;
当遍历图的时候遇到第一个穿梭机时,将所有穿梭机的坐标入队,即下一步可一从任意一个穿梭机的位置开始搜索;
一道简单的BFS水题
代码:
#include<stdio.h>#include<string.h>struct mark{ short x; short y; int step;}through[2000000],queue[4000000];int n,m;struct mark *head,*tail;char maps[2005][2005];char vis[2005][2005];int queue_empty()//判断队列是否为空 {if(head==tail)return 1;elsereturn 0;}void queue_in(struct mark n){tail++;*tail=n;vis[n.x][n.y]='1';}int isvalid(struct mark k){if(k.x>=0&&k.x<n&&k.y>=0&&k.y<m&&vis[k.x][k.y]!='1'&&maps[k.x][k.y]!='M')return 1;elsereturn 0; } int dx[]={1,-1,0,0};int dy[]={0,0,1,-1}; int main(){head=queue;tail=queue; struct mark start;memset(vis,'0',sizeof(vis));int num=0;scanf("%d%d",&n,&m);getchar();int i, j;char ch;int flag=0;for(i=0;i<n;i++) { for(j=0;j<m;j++) { ch=getchar(); maps[i][j]=ch; if(ch=='N') { start.x=i; start.y=j; start.step=0; } if(ch=='E') { through[num].x=i; through[num].y=j; num++; } } getchar(); } struct mark now,next; queue_in(start); while(!queue_empty()) { head++; now=*head; for(i=0;i<4;i++) { next.x=dx[i]+now.x; next.y=dy[i]+now.y; if(isvalid(next)) { next.step=now.step+1; if(maps[next.x][next.y]=='C') { flag=1; printf("%d\n",next.step); goto K; } if(maps[next.x][next.y]=='E') { //任意门里全部入队 for(j=0;j<num;j++) { through[j].step=next.step; queue_in(through[j]); } } else { queue_in(next); } } } } K:; if(flag==0) printf("Not Happy\n"); return 0;
}
写的有点长 毕竟一小学生AQAQAQAQ
- 文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题 文章标题 文章标题 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- Hibernate笔记一(Hibernate简单配置和操作)
- spring框架中Bean的基本属性及调用外部properties等配置文件的方法介绍
- 【数据压缩】JPEG原理分析及JPEG解码器的调试
- hadoop Wordcount示例 出错
- Spring-2
- 文章标题
- C# 查询Xml文档
- 竞拍胜出者可以携一名宾客与库克在苹果新总部Apple Park共进午餐,时间不超过1小时。除了午餐费不用额外支付,旅行和食宿费都要有买家自己承担。此外,今年的竞拍与往年还有一个很大的不同:不包括苹果即
- Linux下命令行ssh密钥连接服务器
- SurfaceView
- ACM课-Rightmost Digit-规律
- 【LCT】BZOJ2002(Hnoi2010)[Bounce 弹飞绵羊]题解
- iQuery环境搭建
- Chrome浏览器所有页面全部崩溃的解决办法