POJ 3278 基础搜索 BFS 三

断断续续做了一个星期。特此留念纪念/(ㄒoㄒ)/~~

POJ 3278 : http://poj.org/problem?id=3278

正确题意:原点为0,起点为n,终点为k,小人自起点走到终点的最少步数为几步。

  走法有: +1,-1,乘2  三种

n,k <100000

 

PS: 如果起点在终点的右边,那么小人就只能  -1  的走法了

 

一个星期的错误经历:

      起初的不明白-1操作的意义是什么......  想只要乘2后一直在终点前面就乘2,然后慢慢的+1操作就好了。       事实证明样例5 17 都过不了。

      于是明白自己的愚蠢。在算法后添加   讨论一下到乘2乘到超过终点,在倒回去。                                               事实证明样例还是过不了。

 

       细细思考,才明白自己想的太蠢,果然是搜索题。每走一步都对 -1,+1,乘2 三种走法进行搜一遍。防止重复走,标记到达每个点的最少步数。

      写着写着就变成递推了......每一个点的最少步数都是 能够到达此点的前面点的最少步数 加一。这不是动态规划么?

       想了想有点小激动,结果写了半天都没写出来。

       由于有-1,+1 操作,动态规划是问题由同类型子问题决定。而这个由-1的子问题和+1的后问题决定,没法推了.....

       受不了了。想,难不成要对 100000的数组标记暴力搜吗?这样的方法是不是太渣没有逼格?而且DFS怎么写出来剪枝了还是超时......

       想来想去想不出来,又不愿意用朴素办法。

 

        一个星期后。只能无奈的百度看众位前辈的解题办法。

        还真的是对 100000的数组标记搜索。  但用的是BFS......

        垂头丧气的写出代码......

 

还有两个小插曲......

         起初以为起点在终点的右边时,就将 起点与终点 swap  一下继续算。  也就是   在输入 5 17 时,与输入  17 5 时的输出是一样的。

          然而5 17 输出4, 17 5 输出12 。当起点大于终点时,输出二者之差。

          最后,写完了BFS。依然是错的。

          实在是受不了了。不知道错在哪里。研究了很久,和别人的AC代码进行逐条比对,消耗一个晚上的时间。

          终于发现。错误原因是,数据量太大,BFS的队列开为局部变量会溢出。

.......把队列改为全局变量终于TM  A了。。。。。敲打敲打敲打敲打

 

BFS思路:

 

  队列开始装入首点。 标记首点。                                               

  取点;三种走法,只要未溢出,并且都未标记过,就放入队列并标记;     (队列里的都是前面未标记,现在刚标记的)清晰

  判断终点标记是否已标记,则终止 

   ——(重复至空)                                                                                          把拓展开的点   没标的的放进去标了

 

 

 

 

 

 

上BFS代码

 

#include"cstdio"
#include"queue"
#include"cstring"
#include"algorithm"
using namespace std;
#define inf 100001
int book[inf];
int n,k; 
queue<int>q;
int bfs()
{
    memset(book,-1,sizeof book);
    while(!q.empty())q.pop();
    
    q.push(n);
    book[n]=0;
    while(!q.empty())
    {
        int t=q.front();q.pop();
        for(int i=0;i<3;i++)
        {
            int tag;
            if(i==0)tag=t*2;
            else if(i==1)tag=t+1;
            else tag=t-1;

            if(tag<0||tag>=inf)continue;
            if(book[tag]==-1)
            {
                book[tag]=book[t]+1;
                q.push(tag);
            }
            if(tag==k)return book[k];
        }
    }
}
int main()
{

    scanf("%d%d",&n,&k);
    if(n>=k)printf("%d\n",n-k);
    else printf("%d\n",bfs());

    return 0;
}

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值