广度优先遍历队列实现
来源:互联网 发布:淘宝客服部门奖罚制度 编辑:程序博客网 时间:2024/05/22 01:50
本周做了两道题,Fast Robot和Picking up Jewels
先说Fast Robot,要求找出从起点到终点最少拐弯次数。
这道题其实有一种很简单的算法:
1. 从起点开始,将拐1次弯的点全部入队,map[i][j].path全部标记成1(并且标记为已访问),然后起点出队。
2. 拐一次弯的第一个点出队,将第一个点作为起点,所有拐一次弯并且未入队的点入队,即总计拐两次弯的点入队。以此类推,直到将所有的拐一次弯的点全部出队。
3. 同理所有的可以走到的点都会入队出队,直到找到终点。
在此原理的基础上,只要找到了终点,那就是最短的拐弯次数。
可是做的时候并没有去思考过多,上来就用了特别朴素的方法,也特别复杂。换了好几次尝试,从不用指针实现的队到用指针实现的队,最后又换回了不用指针实现的队。
首先
int DIR[4][2] ={{-1,0},{0,1},{1,0},{0,-1}}; //正点方向顺时针 上右下左
void BFS(Node start, Node end) {Node t1;enqueue(start); // 将起始点进队int newValue = 0;int i;int dx = 0, dy = 0;while(!isEmpty()) { // 如果队不为空t1 = dequeue(); // 出队for(i=0; i<4; i++) //扫描当前节点的4个方向{dx = t1.x+DIR[i][0];dy = t1.y+DIR[i][1];if(dx == end.x && dy == end.y){if(t1.dir != i) //如果当前节点方向与即将要前进的方向(到终点)不一致,则拐弯数+1{Answer = Answer<t1.value+1?Answer:t1.value+1; //比较新的路径的拐弯数和当前所记录的最小值,取小的数} else {Answer = Answer<t1.value?Answer:t1.value;}#ifdef TESTcout<<"find end!:"<<dx<<","<<dy<<", Answer = "<<Answer<<endl;printOMap();#endifcontinue; // 终点不进队,所以用continue}if(dx>=0 && dy>=0 && dx<N && dy<M && map[dx][dy].d=='0') // '0'表示可走的路{if(t1.dir != i) //如果当前节点方向与即将要前进的方向不一致,则拐弯数+1{newValue = t1.value+1;}else {newValue = t1.value;}if(map[dx][dy].dir == -1 || newValue<=map[dx][dy].value) { //如果 要判断的点是从没访问过的点 或者 已经访问过但是新的路径拐弯次数少于之前保存的拐弯次数 map[dx][dy].dir = i; // 将所判断的点的方向置为当前行进方向map[dx][dy].value = newValue; // 将所判断的点的拐弯书置为新的路径拐弯次数enqueue(map[dx][dy]); // 进队 这里本来是要用指针来实现的,但是因为本题设计到拐弯数和方向两个变量调控的原因, // 只保存一个值的话会有问题。除非添加多个方向的变量,否则最好是使用拷贝的方式进队}}}}}
我是那种建模想象能力不太好的人,一般都需要画出图来理解,所以我test的方式是把整个map当前的状态绘制了出来。
void printOMap(){cout<<"---------------------N="<<N<<",M="<<M<<endl;int i,j;for(i=0; i<N; i++){for(j=0; j<M; j++){if(map[i][j].value == BMAX){cout<<"*"<<" ";}else{ cout<<map[i][j].value<<" ";}}cout<<endl;}}
7 7 // 7列7行
1 2 7 5 // start end
1111111 // 1是墙,0是路
0000011
1011001
1011100
1011110
1000000
1111111
find end!:4,6, Answer = 5
---------------------N=7,M=7
* * * * * * *
1 0 0 0 0 * *
* 1 * * 1 2 *
* 1 * * * 3 4
* 1 * * * * -1
* 1 2 2 2 * *
* * * * * * *
find end!:4,6, Answer = 3
---------------------N=7,M=7
* * * * * * *
1 0 0 0 0 * *
* 1 * * 1 2 *
* 1 * * * 3 4
* 1 * * * * -1
* 1 2 2 2 2 2
* * * * * * *
因此最小的拐弯数就是3了。
在做这道题的时候,我曾遇到一个百思难得其解的问题。就是小的数据运算结果都是OK的,但是一碰到大的数据的时候,DFS后的数组输出就有问题了。
100x120的数据为什么输出变成了7行1列呢。研究了半天没整明白。最后在老大的帮助下,发现原来我的循环队列写成了顺序队列,40000的长度都没打住,把N和M的空间给踩了,可见这复杂的。也由此暴露出来了一个问题,这基础多不牢固能犯这错误,哈哈。
现在来说说队列怎么写吧。
typedef struct {int x;int y;int dir;int value;char d;}Node; // 节点结构体Node map[MAX][MAX]; // 节点数组用于存储maptypedef struct {Node data[LENGTH];int rear;int front;}Queue; // 队列结构体Queue que; // 队列
Node map[MAX][MAX]; 输入是char型的字符,那么怎么存储成Node的数组呢
如果是char map[MAX][MAX],那么你可以这样
for(i=0; i<N; i++) {
cin>>map[i];
}
然而Node型的你则需要逐个地输入了。
for(i=0; i<N; i++){ for(j=0; j<M; j++) { cin>>map[i][j].d; map[i][j].x = i; map[i][j].y = j; map[i][j].dir = -1; map[i][j].value = 999999; }}
队列一般需要队空、队满、入队、出队、获取对头、初始化等方法。
bool isEmpty(){ if(que.rear == que.front){ return true; }else { return false; }}bool isFull(){ if((que.rear+1)%LENGTH == que.front){ return true; }else { return false; }}void enqueue(Node n){#ifdef QLOG cout<<"enqueue:"<<n.x<<","<<n.y<<",dir = "<<n.dir<<",value = "<<n.value<<endl;#endif if(!isFull()) { que.data[que.rear] = n; que.rear = (que.rear+1)%LENGTH; // que.rear++; // 顺序队列 } else { #ifdef QLOG cout<<"enqueue fail because queue is full"<<endl;#endif } }Node dequeue(){ Node n = que.data[que.front]; if(!isEmpty()) { que.front = (que.front+1)%LENGTH; //que.front++; // 顺序队列#ifdef QLOG cout<<"dequeue:"<<n.x<<","<<n.y<<",dir = "<<n.dir<<",n.value = "<<n.value<<endl;#endif } else {#ifdef QLOG cout<<"Queue is empty"<<endl;#endif } return n;}Node getTop(){ Node n = que.data[que.front];#ifdef QLOG cout<<"getTop:"<<n.x<<","<<n.y<<",dir = "<<n.dir<<endl;#endif return n;}void initQueue(){ que.front = que.rear = 0;}
到此基本上这个问题就说完了。
- 广度优先遍历队列实现
- 图广度优先遍历(队列实现)
- C语言队列实现广度优先遍历
- 利用队列实现图的广度优先遍历
- 广度优先搜索,队列实现
- 图的广度优先遍历::邻接矩阵+队列.
- 容易理解的python用队列实现广度优先遍历文件
- 图的深度优先遍历和广度优先遍历实现
- 利用队列实现广度优先搜索
- 广度优先搜索(队列实现)
- 深度、广度优先遍历算法C实现
- 广度优先遍历二叉树实现
- 如何实现广度优先遍历(BFS)
- 如何实现广度优先遍历(BFS) .
- 广度优先遍历 BFS C实现
- 广度优先遍历(c/c++实现)
- 深度、广度优先遍历算法C实现
- 深度优先和广度优先遍历及其 Java 实现
- mysql 性能优化方案
- RSync实现文件备份同步
- ubuntu下opensips安装配置
- ListView设置EmptyView
- hdu 3038 How Many Answers Are Wrong(并查集变种)
- 广度优先遍历队列实现
- 机器学习系列(7)_机器学习路线图(附资料)
- pat1009:说反话
- 1099. Build A Binary Search Tree (30) 给定二叉搜索树插值
- 2016春季训练——树状数组
- POJ 3279
- VMware10安装Ubuntu12.04后无法进入图像界面
- 异常:UnicodeEncodeError: 'ascii' codec can't encode characters 处理办法
- [网络流24题][codevs1906]最长递增子序列(dp+isap)