简单算法 广搜题

题目:农夫知道一头牛的位置,想要抓住它。农夫和牛都于数轴上 ,农夫起始位于点 N(0<=N<=100000) ,牛位于点 K(0<=K<=100000) 。农夫有两种移动方式: 1、从 X移动到 X-1或X+1 ,每次移动花费一分钟 2、从 X移动到 2*X ,每次移动花费一分钟 假设牛没有意识到农夫的行动,站在原地不动。最少要花多少时间才能抓住牛?
Input
一行: 以空格分隔的两个字母: N 和 K
Output
一行: 农夫抓住牛需要的最少时间,单位分钟
Sample Input
5 17
Sample Output
4
Hint
农夫使用最短时间抓住牛的方案如下: 5-10-9-18-17, 需要4分钟.

解答:
首先呢,明确一点,人可以三种行进方式,向左移动一步,向右移动一步,以及以自己的点为基础两倍的行进,三种方式都是1分钟时间,首先呢不要纠结,为啥时间这样玩我,不重要。只需要明白,在某一点上,接下来的你可以有三种方式行动。三种状态我们叫作,后面有用。题目读完上代码

		#include"stdio.h"
		#include <iostream>
		#include <string.h>
		#include <queue>//队列需要的头文件
		using namespace std;
		bool sign[100005];//这个数组的作用是标记已经行动的点,理解成数轴,你在上面的某个位置,想象成下标号的大小,用下标号作尺子
		int n,k;//这里是输入的两个值初始位置   以及   末尾
		struct state//状态结构体
		{
			int z;//这里一会儿理解
			int step;这里一会儿理解
		};
		bool judge(int c)//检查下一步是否满足有三种
		{
			if(c<-1)
			return 1;//超过数组下标就是不能位置小于0
			if(c>100000)
			return 1;//不能大于移动范围
			if(sign[c]==1)
			return 1;走过的点不能再走
			return 0;//以上三种都满足就返回0
		}
		int bfs()//广搜正式开始
		{
			queue <state> human;//①创建state型队列
		 	memset(sign,0,sizeof(sign));//②是状态数组清零
		 	state start,next;//③定义现在位置 与 接下来的位置的结构体变量,每一个变量都有三种状态,步数,自己的位置,以及下一步可以走三种方式
		 	start.z=n;//④初始位置的坐标轴赋值
		 	start.step=0;/⑤初始的步骤为零
		 	sign[n]=true;//⑥让这个点标记成已经经过的状态
		 	human.push(start);//⑦ 把第一个位置放入队列         以上七步是对广搜的初始条件做准备     
		 	while(!human.empty())//仔细理解这一步,有不懂的问我
		    {
		 		 start=human.front();    //取出队列的数据并且赋值,为啥重复操作,是为了承接下面的步骤
		          human.pop();//删除队列第一个进入的数据
		        if(start.z==k)//判断是否满足我们需要的数字,这作为广搜的结果
				{
					return start.step;
				}  
		        for(int i=0;i<3;i++)//为啥是三,就因为有三种走的方式,每一种进入的数据(比如初始数据start),记录下他下一个可能的情况并储存进入队列。
		        {
		        	int resul=0;
		        	if(i==0)
		        	 {resul=start.z-1;}
		        	else if(i==1)
		        	 resul=start.z+1;
		        	else if(i==2)
		        	 resul=start.z*2;//以上三种结果随着i的改变而变化
		        	if( judge(resul)) //检查每一种结果是否满足,不满足直接进行循环,满足执行下面的
		                continue;   
			 		next.z=resul;//next只是作为一个承接变量,使他得到的值放入队列,三次执行了三次放入
		        	next.step=start.step+1;//同一个数据的三种行进方式都算执行了一步,
		        	sign[resul]=true;//记录经过这个点
		        	human.push(next);//插入了这个点进入队列
		        }
		 	} 
		} 
		int main()
		{
			while(~scanf("%d %d",&n,&k))
			{
				int move=bfs();
				printf("%d\n",move);
			}
			return 0;	
		}
		//如果用 5    17举例
		程序会这样执行

进入一个5 拿掉之后,start传值得到5这个位置三个结果
4 6 10,并且这三个同时进入队列,因为5被front了所以4为开头,又接着处理4所以结果是
5
4 6 10
3 5 8 5 7 12 9 11 20,又因为一些点被标记比如5
所以从队列的出来值以次是
5 4 6 10 3 8 7 12 9 11 20 2 16 14 13 24 18 22 19 21 40 1 15 17 32 28 26 23 25 48 3
6 44 38 42 39 41 80 0 30 共计4步
并且广搜是一层一层搜,5为一层,4610第二层 4 6 10的三种情况第三层

以次类推。。
加油

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值