poj 3278(bfs宽度优先搜索)

题目大意:给定一个数N (O≤N≤100000),变成另一个数K(O≤K≤100000),允许的操作是乘以2,或者加减1,问最少要几步才能完成?

题目分析: 一般这种求有多少种方案的感觉用bfs 的居多。反正这题是用bfs的,然后广度优先搜索都是要用到队列的,然后感觉这题就比较裸吧,只是一维的,相对于之前做的那个抄作业(三维bfs),不过比较尴尬的是那个一直不知道哪地方错了。就题论题。这题就是先使满足条件的*2,+1或者-1,然后压入队列,让上一次的队头出队列。啊呀,感觉好难讲,还是结合代码讲吧,最好手算模拟一下,当初我也是理解不了,然后手算模拟的,才明白的。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
struct node{
	int o,count;//o是表示当前的步数所到达的位置,count是统计到达此的步数 
}q,p;
bool vis[400010];//作为标记数组,标记已经走过的点 
int main(){
	int n,k;
	while(~(scanf("%d%d",&n,&k))){
		p.o = n;//表示初始点的位置 
		p.count = 0;//表示到达此点时的最小步数 
		queue<node>bfs;//建一个队列 
		memset(vis,false,sizeof(false));//初始化标记数组的值,设为都没有访问过 
		bfs.push(p);//将p压入队列 
		vis[p.o ]=true; //标记初始点为已经访问过的点 
		while(!bfs.empty()){//除非队列为空,否则此循环不停止 
			p=bfs.front();//把队列的初始值赋值给p,每一次循环都要做,这个很重要。 
			if(p.o == k){
				printf("%d\n",p.count );
				break;
			}//如果到达目的点,则中断,输出步数 
			p.count ++;//此点的步数加1,按照点的运动规则,到达下列的点 
			if(p.o < k){//如果大于k的话,就*2或者+1,这样可以省时 
				q=p;//先找一个q代替p,以保证下面的q的操作正常 
				q.o = p.o*2;
				if(vis[q.o] ==false && q.o ){//如果此点没有被访问过,就更新成已经访问过的 
					vis[q.o]=true;
					bfs.push(q);
				}
			    q=p;
			    q.o ++;
				if(vis[q.o]== false){
					vis[q.o]=true;
					bfs.push(q); 
				}
			}
			if(p.o > 0){//这个本来想是》k的,后来一想,还是》0对 
				q=p;
				q.o --;
				if(vis[q.o ]== false ){
				    vis[q.o ]=true ;
				    bfs.push(q); 
				}
			}
			bfs.pop(); //已经搜过的点就出队列。 
		}
	}
	return 0;
} 


  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值