POJ3278

/**题目大意:
农场主约翰得知了一头逃跑的母牛的行踪,想立即抓住她。
他从一个点开始,N(0≤N≤100000)在数轴上,
牛点K(0≤K≤100000)在同一数轴。
农夫约翰有两种交通方式:走路和传送。
*行走:FJ可以在一分钟内从任意点X移动到点X - 1或X + 1
*传送:FJ可以从任何点X点2×X在一分钟。
如果这头牛没有意识到它的追猎,
它一点也不动,
农夫约翰需要多长时间才能把它找回来?
输入
第1行:两个空格分隔的整数:N和K
输出
第一句:用最少的时间,几分钟,
农夫约翰就能抓住这头逃亡的牛。
样例输入
5 17
样例输出
4
提示
农民约翰到达逃亡牛的最快方法是
沿着以下路径移动:5-10-9-18-17,
需要4分钟。
**/

下面有两段代码,第一段是爆栈的DFS做法,结果是run time error

第二段是AC代码。总结来讲:BFS的优点是第一个找到的节点一定是最早找到的目标节点

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k;//表示主人的坐标和牛的坐标
int t,tt;//表示最小的时间和本方案的时间,换算公式为:t=min(tt,t)
int visited[100001];
void dfs(int tt,int n)//对时间进行值传递,不要改变大小
{
    if(n==k)
    {
        t=min(tt,t);
        return;
    }
    if(n<0||n>100000)
        return;
    if(visited[n-1]==0&&(n-1)>=0)
    {
        visited[n-1]=1;
        dfs(tt+1,n-1);
        visited[n-1]=0;
    }
    if(visited[n+1]==0&&(n+1)<=100000&&k>n)
    {
        visited[n+1]=1;
        dfs(tt+1,n+1);
        visited[n+1]=0;
    }
    if(visited[2*n]==0&&(2*n)<=100000&&k>n)
    {
        visited[2*n]=1;
        dfs(tt+1,2*n);
        visited[2*n]=0;
    }
}
int main()
{
    cin>>n>>k;
    memset(visited,0,sizeof(visited));
    t=100005;
    tt=0;
    dfs(tt,n);//表示从tt=0从n位置开始的搜索
    cout<<t<<endl;
    return 0;
}
/**
本题目的搜索条件比较特殊:
k>n时,可以2*n,[可以n-1](很重要!)
可以n+1
k<n时:只能n-1;即:n-1没有使用if的限制
n+1和2*n只能k>n的时候!否则会造成栈的溢出
**/
#include<iostream>
#include<cstring>
using namespace std;
int vis[100001];//访问标记数组,判断节点是否入队
struct node
{
    int x;//记录此节点的坐标
    int num;//记录开始访问此节点坐标的最早时间
} link[100001];
int t;//最短时间
int pp,qq;//当前指针和入队指针
int n,k;//主人和牛的坐标
bool judge(int x)
{
    if(x<0||x>100000||vis[x]==1)
        return false;
    else
        return true;
}
void bfs()
{
    if(n==k)
    {
        t=0;
        return;
    }//排除特殊情况
    int step[3];
    while(pp<qq)
    {
        int flag=0;//标记目标节点是否被找到
        step[0]=link[pp].x-1;
        step[1]=link[pp].x+1;
        step[2]=2*link[pp].x;
        for(int i=0; i<3; i++)
        {
            int xx=step[i];
            if(judge(xx))//节点没有入队,且满足条件,入队
            {
                if(xx==k)
                {
                    t=link[pp].num+1;
                    flag=1;
                    break;
                }
                else//节点入队
                {//节点入队时,新节点进行全部信息的更新,表示搜索的更新
                    link[qq].x=xx;
                    link[qq].num=link[pp].num+1;
                    vis[xx]=1;
                    qq++;
                }
            }
        }
        if(flag)//目标节点找到,结束
            break;
        pp++;//节点没找到,按照队列顺序遍历下一个节点
    }
}
int main()
{
    cin>>n>>k;
    pp=qq=0;
    memset(vis,0,sizeof(vis));
    link[qq].num=0;
//坐标为n的节点入队,开始搜索
    link[qq].x=n;
    vis[n]=1;
    qq++;
    bfs();
    cout<<t<<endl;
    return 0;
}


 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值