您的位置:首页 > 编程语言 > C语言/C++

POJ 3278 Catch That Cow【C语言版】

2015-05-16 19:14 246 查看
我的第一道BFS题,还是按照习惯在网上搜索题解,令人郁闷的是大部分都是C++版的,用了queue库。而且可能因为这道题太水,好不容易找到的C语言版的解题报告中的注释又对新手不太友好,不是特别详细,有的讲的很齐全但是代码太难看了我拒绝看 = =。。。知道我遇到了这个人的博客,当然注释也不是很齐全,但是胜在代码啰嗦(划掉),马上就看懂了。所以我决定在他的解题报告代码的帮助下来开始我人生中第一道BFS题(这意味着我的代码也是啰嗦的),很感谢原博主的题解。
http://blog.csdn.net/u013445530/article/details/19911789
下面分析一下这道题,算是自学吧。蒟蒻没有办法一瞬间就融会贯通T0T

首先遇到这样一道题,应该做什么呢?先画一个解答树好了。。



DFS所搜索的答案一定出现在叶结点上,而这道题中我们不知道这个解答树会有多深,所以不能用DFS一条一条进行搜索,或者说这样做是非常低效的。所以这道题使用了BFS,就是层次遍历,按照逐层加深的顺序遍历这课解答树,得到答案所在的树的深度。

在DFS时,是递归向下的,所以我们不需要额外存储结点,而BFS中在某一层遍历完成前,需要存储本层的所有结点,在本层遍历完成后按照存储顺序寻找下一层的元素,所以这里使用了先进先出的队列。

C++是有一个queue库的,而C语言则需要借用数组等等工具来模拟这样的一个队列。

在这里还有一点,为了防止这棵解答树无限深入,必须保证树上的元素互不相等,也就是说要剪掉重复的树枝。所以这里还需要一个数组来记录某个数是否曾经被访问过。

代码如下
#include<stdio.h>
#include<string.h>
struct A{
int state;
int step;
}queue[100005];                           // 结构体数组用来模拟队列,数组元素包含两个数据,state代表遍历到的数值,step所经历的步数
int vis[100005];                          // 这个数组用来存储访问情况
int n, k;
int bfs( int aim);
int main(void){

scanf("%d%d", &n, &k);
if( n >= k) printf("%d\n", n-k);  // 如上图可知,n>=k的最优解一定是每一步都向后退
else printf("%d\n", bfs(n));
return 0;
}
int bfs( int aim){
struct A temp;                    // 结构体元素用来当做循环单位
int head, rear;                   // 队首队尾指针
memset( vis, 0, sizeof(vis));
vis[aim] = 1;
head = rear = 0;
queue[rear].state = aim;          // 起点作为第0个元素入队
queue[rear++].step = 0;           // 此时也是第0步,然后队尾指针向后移动

while( head < rear){              // 队空时结束循环
temp = queue[head++];     // 队首元素出队
// 第一种操作
if( temp.state+1 > 0 && temp.state+1 <= 100005 && !vis[temp.state+1]){
queue[rear].state = temp.state + 1;               // 操作后的元素入队,记录数值以及步数
queue[rear++].step = temp.step + 1;
vis[temp.step+1] = 1;                             // 此时标记访问
if( temp.state + 1 == k) return temp.step + 1;    // 如果和目标相等则返回步数
}
// 第二种操作
 if( temp.state-1 > 0 && temp.state-1 <= 100005 && !vis[temp.state-1]){
queue[rear].state = temp.state - 1;
queue[rear++].step = temp.step + 1;
vis[ temp.state-1] = 1;
if( temp.state-1 == k) return temp.step + 1;
}
// 第三种操作
 if( temp.state*2 > 0 && temp.state*2 <= 100005 && !vis[temp.state*2]){
queue[rear].state = temp.state * 2;
queue[rear++].step = temp.step + 1;
vis[ temp.state*2] = 1;
if( temp.state*2 == k) return temp.step + 1;
}
}
return 0;
}


虽然接触BFS是比DFS晚,不过我觉得DFS可能比BFS更难理解,那一层一层的递归曾经有一阵狠狠地迷晕过我,新手中的蒟蒻伤不起
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: