宽度搜索

8 篇文章 0 订阅
4 篇文章 0 订阅

7-28 宽度搜索

           首先再次说明一下宽度搜索的概念与原理。宽度搜索,就是宽度优先搜索(也叫广度优先搜索),所以宽度是优先。我们都知道深度搜索是一下子搜到底,然后再通过回溯之类的方式返回到上一个分支,然后继续往下搜。也就是深度优先;而宽度优先搜索就是一层一层地找:先找一层,记录下来,然后继续搜下一层。

      这时我们就需要两个指针:headtailhead是头指针,用来标记上一层的第一个。tail就是尾指针,用来标记当前的位置。head每移动一个,那就是到了某一个分支的开始点,然后就用一个循环访问这个开始点的每一个分支,并用一个一位数组把它们记录下来,然后在访问跟head同一层的另外的开始点。这一层全部访问完后,就访问下一层的第一个。

宽度搜索 - 周正华 - 周正华的博客

 

具体拿这个图讲一下吧:首先head指向1tail指向2,。然后找到1的分支,然后这个分支记为2,。然后在第B层继续扫描下一个分支点,同时tail++,将尾指针的位置往后移,用数组记录,继续扫3。扫完3后,B层的所有分支都扫完了,然后就到了C层……以此类推。

宽搜就是每搜一层就处理一次,那样就能非常容易地解决“最短路径”“重复”之类的问题。还有,在处理大数据的时候,用深搜可能会超时;可是用宽搜,就会变得很快。所以,宽搜的优点还是蛮多的。

下面可以通过一个问题来展示出宽搜是如何实现的:

 

 

奇怪的电梯(lift

Time Limit:1000MS  Memory Limit:65536K
Total Submit:70 Accepted:40

Description

呵呵,有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1<=i<=N)上有一个数字Ki(0<=Ki<=N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki(K1=3,K2=3,……),从一楼开始。在一楼,按“上”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?

Input

输入文件共有二行,第一行为三个用空格隔开的正整数,表示N,A,B(1≤N≤200, 1≤A,B≤N),第二行为N个用空格隔开的正整数,表示Ki。

Output

输出文件仅一行,即最少按键次数,若无法到达,则输出-1。

Sample Input

5 1 5
3 3 1 2 5

Sample Output

3

 

下面是程序:

#include <iostream>

using namespace std;

 

long long N,A,B;

long long a[201];

bool pd,f[2001];

long long head=1,tail=2;

long long now[2001],step[2001];

void bfs();

 

int main()

{

      cin>>N>>A>>B;

      if(A==B)

      {

           cout<<0<<endl;

           return 0;

      }

      int x;

      for(int i=1;i<=N;i++)

           cin>>a[i];

      bfs(); 

      if(!pd)

           cout<<-1<<endl;

     

      return 0;

}

 

void bfs()

{

      now[1]=A;

      step[1]=0;

      f[A]=true;

      for(;head<=tail;head++)

      {

if((now[head]-a[now[head]])>0 && !f[(now[head]-a[now[head]])])

           {

                 now[tail]=now[head]-a[now[head]];

                 step[tail]=step[head]+1;

                 f[now[tail]]=true;

                 if(now[tail]==B)

                 {

                      pd=true;

                      cout<<step[tail]<<endl;

                      return ;

                 }

                 tail++;

           }

          

             if((now[head]+a[now[head]])<=N && !f[(now[head]+a[now[head]])])

           {

                 now[tail]=now[head]+a[now[head]];

                 step[tail]=step[head]+1;

                 f[now[tail]]=true;

                 if(now[tail]==B)

                 {

                      pd=true;

                      cout<<step[tail]<<endl;

                      return ;

                 }

                 tail++;

           }         

      }

      return ;

}

我们来看一下这个程序(关键是在bfs这部分)。首先定义了一个head头指针与一个tail尾指针。tail指针记录所在的结点,而head指针就是来记录tail指针结点的上一个分支。这样就可以通过数组中下标为tail的元素继承下标为head的元素中的内容,如步数、时间、方位等:即step[tail]=step[head]+1。当tail找不到分支时,就会停止加1,那么head指针跟上tail指针时,也就是全图已经扫描过一遍了,那就停止搜索。

      需要注意的是:数组中以head为下标的元素必须初始化(即step[1]=0,不然的话就会让这个搜索毫无用处,可能还会导致死循环。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值