POJ 3278,抓牛问题(BFS)

15 篇文章 0 订阅
14 篇文章 0 订阅

题目链接:戳此进入

这道题如果用DFS就是一路走到头没法向回拐,所以不能用DFS,我们用BFS+队列,广搜一下,

第一先确定人的位置,之后确定牛的位置,如果人在牛前,人就只能后退,那差几步就是几分钟。

第二种是牛在人前面,然后人开始找牛,三种方法,步数+1,步数-1,步数*2,

然后开始遍历,先把人开始的位置压入队列,遍历下面3个地方,判断是否找到,判断是否越界,然后把队列头依次拿出,每次拿出都会往下遍历3种情况,步数+1,步数-1,步数*2,如果有点遍历过了,就不再遍历,每次遍历同时更新步数,

下面是实现代码

#include<iostream>
#include<queue>
#include<cstring>
#include<cstdio>
#include <algorithm>
using namespace std;
 
queue<int> q;
int  m,n;
int step[100010];
int vis[100010];
int rear,front;//rear表示下一步 
int BFS(){
	int i;
	q.push(n);//把农民的位置压入队列 
	step[n]=0;//步数记为0 
	vis[n]=1;标记这个点走过 
	while(!q.empty()){//队列不为空哦时执行 
		front=q.front();//最开始的位置 
		q.pop();//弹出队列头 
		for(i=0;i<3;i++)//三种走法,三种循环 
		{
			if(i==0)
			rear=front+1;//第一种下一步+1 
			if(i==1)
			rear=front-1;//第二种下一步-1 
			if(i==2)
			rear=front*2;//第三种步数翻倍 
			if(rear>=0&&rear<=100000&&vis[rear]==0)//判断是否越界,并且这一步没有走过 
			{
				vis[rear]=1;//标记这一步走过了 
				step[rear]=step[front]+1;// 步数+1 
				q.push(rear);//将当前位置压入队列 
			}
			if(rear==m)return step[rear];
		}
	}return -1;
	
}
 
int main(){
	
	cin>>n>>m;
		memset(step,0,sizeof(step));//初始化为0 
		memset(vis,0,sizeof(vis));//初始化为false
		cout<<BFS();
	
	return 0;
}

第二种方法是定义一个结构体


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
struct node
{
	int x;
	int c;
} pos[200000];
int n,k;
queue<node> q;
bool vis[200000];//为什么设置成200000呢?因为p*2的时候就越界了虽然不做判断,但是需要这个范围,如果没有程序会跑崩溃
int bfs()
{
	int p,cnt;
	while(!q.empty()){
		p=q.front().x;//记录位置 
		cnt=q.front().c;//记录步数 
		q.pop();//取出队列第一个 
		
		if(p==k) return cnt;//如果找到牛就返回了 
		if(!vis[p-1]&&p>0)//能够退一步  
		{
			vis[p-1]=1;
			pos[p-1].c=cnt+1;
			pos[p-1].x=p-1;
			q.push(pos[p-1]);
		}
		if(p<k)//如果人再牛后面 
		{
			if(!vis[p+1])//能够前进一步 
			{
				vis[p+1]=1;
				pos[p+1].c=cnt+1;
				pos[p+1].x=p+1;
				q.push(pos[p+1]);
			}
			if(!vis[2*p])
			{
				vis[2*p]=1;
				pos[2*p].c=cnt+1;
				pos[2*p].x=p*2;
				q.push(pos[2*p]);
			}
		}
	}
}
int main(){
	cin>>n>>k;
	memset(vis,0,sizeof(vis));//初始化 
	memset(pos,0,sizeof(pos));//初始化 
	vis[n]=1;//标记这个位置已经搜索过了 
	pos[n].x=n;//给结构体赋值(位置) 
	pos[n].c=0;//给结构体赋值 (步数) 
	q.push(pos[n]);//把第一个结构体拉入列队 
	cout<<bfs()<<endl;;
	return 0;
}

 

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<math.h>
#include<queue>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 100010;
int x, y;
int ans = 0;

bool inq[maxn];
struct node{
	int x;
	int step;
	node(){
		step = 0;
	}
};

bool check(node now){
	if(now.x < 0 || now.x > 100010){
		return 0;
	}
	return 1;
}
int BFS(node now){
	queue<node> q;
	q.push(now);
	inq[now.x] = 1;
	while(!q.empty()){
		node front = q.front();
		if(front.x == y){
			return front.step;
		}
		q.pop();
		node next;
		for(int i = 1; i <= 3;i ++){
			if(i == 1)
				next.x = front.x + 1;
			else if(i == 2)
				next.x = front.x - 1; 
			else 
				next.x = front.x * 2;
			if(check(next) && !inq[next.x]){
				inq[next.x] = 1;
				next.step = front.step + 1;
				q.push(next);
			}
		}		
	}
	return 0;
}

int main(){
		scanf("%d%d", &x, &y) ;
		node start;
		start.x = x;
		int ans;
		ans = BFS(start);
		printf("%d\n", ans);

	return 0;
} 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值