POJ3278

本学期选了学校的算法课程,P大研究生的算法课程难度不小(PS:对于我这种菜狗),加上本科没有学过算法,更是有点被虐的感觉,所以平时更要多加练习

没事的时候就去做题。

POJ3278

,2总时间限制: 
2000ms 
内存限制: 
65536kB
描述

农夫知道一头牛的位置,想要抓住它。农夫和牛都位于数轴上,农夫起始位于点N(0<=N<=100000),牛位于点K(0<=K<=100000)。农夫有两种移动方式:

1、从X移动到X-1或X+1,每次移动花费一分钟
2、从X移动到2*X,每次移动花费一分钟

假设牛没有意识到农夫的行动,站在原地不动。农夫最少要花多少时间才能抓住牛?
输入
两个整数,N和K
输出
一个整数,农夫抓到牛所要花费的最小分钟数
样例输入 5 17 样例输出 4 思路: 这个是典型的广搜问题,因为要求的是最短的路径,类似的有迷宫问题找路之类的,广搜一般要用一个结构体(对象)来代表每一个状态,用一个队列queue来记录先后的访问顺序,并且一定要注意状态的边界条件和状态的转换关系(本期中是位置变化的转换关系),农夫可以向前找(+1 表示),也可以向后找(-1 表示),也是跨距离找(* 2表示) 注意的地方是  1,广搜的时候每次访问完队头的节点后要把它pop出去
2, DFS 和BFS 一般实现时都要用一个大的visited 数组表示是否已经访问过了。
3, 多种情形扩展时,不能用 else if 而是用并列的 if (DFS也一样),否则搜索空间会减小,一些状态不会被枚举到,else if 直接跳过剩下的cases,一些点就没有入队。 这是一个隐藏的坑。
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;

const int MAXN = 100000;
int visited[MAXN+10]; //判重标记,visited[i] = true表示i已经扩展过
int N,K;
struct step1{
	int x;
	int steps;
	step1(int xx,int ss):x(xx),steps(ss){
	}
};
queue<step1> q;
/*
注意的地方是 广搜的时候每次访问完队头的节点后要把它pop出去。
多种情形扩展时,不能用if else 而是用并列的 if (DFS也一样),否则搜索空间会减小。 
*/
int main(){
	cin>>N>>K;
	memset(visited,0,sizeof(visited));
	q.push(step1(N,0));
	visited[N]=1;
	while(!q.empty()){			
		step1 curS = q.front();
		if(curS.x==K){
			cout<<curS.steps<<endl;
			return 0;
		}
		if(curS.x-1>=0&& !visited[curS.x-1]){
			q.push(step1(curS.x-1,curS.steps+1));
			visited[curS.x -1] = 1;
		} if(curS.x+1<=MAXN && !visited[curS.x+1]){
			q.push(step1(curS.x+1,curS.steps+1));
			visited[curS.x +1] = 1;			
		} if(curS.x*2<=MAXN && !visited[curS.x*2]){
			q.push(step1(curS.x*2,curS.steps+1));
			visited[curS.x *2] = 1;
		}		
		q.pop(); //每次出队一个结点 
	}
}
希望坚持下去!!!每天3题!!!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值