文章标题

来源:互联网 发布:万讯网络中控 编辑:程序博客网 时间: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

原创粉丝点击