搜索专题(dfs and bfs)

搜索,顾名思义,就是对某样事物进行寻找。好了我就不多废话了。搜索有多种形式,常见的dfs(深度优先搜索)和bfs(广度优先搜索)等等,这也就是今天的主要内容:

1.dfs:深度优先搜素,就相当于你去逛街,有很多条街相通,你选择先走任意一条街,如果没有自己想要去的店,那么回到上一个路口,再选择一条没走过的路继续走到底。如:因式分解,即输入n,求将n因式分解的总方案数。

首先,看到这题,我首先想到的是用递归去求n的各个因式,但当n足够大时,这种递归写法很显然会超时,这时就要进行一定的优化了,考虑到n的因式可能还有因式,就不难想到,n的因式的总方案数也一定包括了n的因式的因式。这么说有点绕口又有点难懂,那么具体看看代码:

#include<bits/stdc++.h>
using namespace std;
long long n,a[15000],b[15000],ghj=1;
int main()
{
b[1]=1;
cin>>n;
for(int i=1;i*i<=n;i++)
{
if(n%i==0)
{
a[ghj++]=i;//n的小于根号n的约数; 
if(i*i!=n)
{
a[ghj++]=n/i;//n的大于根号n的约数; 
}
}
}
sort(a+1,a+ghj);
for(int i=1;i<ghj-1;i++)
{
for(int j=i+1;j<=ghj-1;j++)
{
if(a[j]%a[i]==0) b[j]+=b[i];//如果a[j]是a[i]的倍数,那么a[j]的方案数要加上a[i]的方案数; 
}
}
cout<<b[ghj-1]<<endl;//相当于输出n的方案数; 
return 0;
}

看了这个,就可以很容易的想到n的因式之间的关系(虽然我没用递归(*^__^*) 嘻嘻),知道了他们之间的关系后,就不难求出n的方案数了。(不得不说代码是真的又臭又长)

2.dfs:广度优先搜索,就好比我现在要去洗手间,我要找一条最近的路,假设我有很多分身,那么分身们向不同方向走去,在时间相同的情况下,第一个到达洗手间的分身所走的路线一定是最短的(速度也相同)。典型题如:奇怪的电梯,从a楼到b楼,电梯在每个楼层所可以上升或下降的层数不同,求出最少次数。

看完题目,我的第一反应就是模拟一下电梯的(鬼畜)移动,在既可上升又可下降时,用bfs进行搜索,具体代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,a,b,k[201]={},here,m,ans,minnest=1000000;
bool look[201]={};//标记,指该电梯是否到达过
void bfs(int here,int y){
 if(y>=minnest) return;//如果比已有方案的次数要多,显然不是最优方案,直接返回
 if(here==b){//如果到达了b层
     minnest=min(minnest,y);//那么比较它的次数与原有方案的次数
     return;
 }
 if(here-k[here]>0&&look[here-k[here]]==false)//第一种情况:如果可以下降且下降后到达的楼层未曾到达过
 {
  look[here-k[here]]=true;//标记为此楼层已到达过
  bfs(here-k[here],y+1);//递归,继续移动
  look[here-k[here]]=false;//递归完毕后将此楼层标记为未到达过(因为仅当此时电梯选择下降时才到达过次楼层)
 }
 if(here+k[here]<=n&&look[here+k[here]]==false)//第二种情况:如果可以上升且上升后到达的楼层未曾到达过
 {
  look[here-k[here]]=true;
  bfs(here+k[here],y+1);
     look[here-k[here]]=false;//同上
 } 
}
int main()
{
 cin>>n>>a>>b;
 for(int i=1;i<=n;i++)
 {
     cin>>k[i];
 }
 bfs(a,0);
 if(minnest==1000000) cout<<"-1"<<endl;//如果未曾到达过
 else cout<<minnest<<endl;
 return 0;
}

整个也就是个类似模拟,在电梯可以进行多种(两种)情况的移动时分别模拟,最后得出最少次数。(仍然是又臭又长)

 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值