浅谈bfs与dfs

  这几天刷了点bfs与dfs的题,来总结下, 

     上~~~~上图

       

咳~咳~咳 错了。。。。。

好了,好了,咋也是正经人,进入主题

dfs

   dfs实叫深度优先搜索算法,起始它只是一种搜索的方法思路,并没有固定的算法格式,假设这样的情景,一个姑娘爱你爱的深沉,被你拒绝了好多次了,可就是不放弃你说“只要你没有结婚,我就有机会”,典型的不撞南墙不回头,一条道走到黑,这种。。。。对,就是这样的,dfs就是有着你追隔壁班女神的这样的执着,说到这里,继续上图。。。。

假设你穿越到古代的你娶了三位小妾,晚上让谁来侍寝苦恼了你好久,你需要一个他们侍寝的顺序

                                                          

             1号小姐姐                              2号小姐姐                                       3号小姐姐

 

跟随着红色箭头你就可以得到3位美妾的侍寝的所有可能的顺序了,我就问你你选哪种,我选三在最后一夜的,别问我为什么,就因为有句话叫先苦后甜~ 嘻嘻嘻。DFS的重要点在于状态回溯。代码如下

  

#include <iostream>
#include <algorithm>
using namespace std;
int n;
const int N =8;
int path[N];
bool st[N];
void dfs(int x){
    if(x==n){
        for(int i=0;i<n;i++){
             cout<<path[i]<<" ";
        }
        cout<<endl;
    }
    for(int i=1;i<=n;i++){
        if(!st[i]){
            path[x]=i;
            st[i]=true;
            dfs(x+1);
            st[i]=false;//状态回溯,
        }
    }
}
int main(){
    cin>>n;
    dfs(0);
    return 0;
}

 POJ 1321-棋盘问题

    在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别。要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C。

 input :   

2 1
#.
.#
4 4
...#
..#.
.#..
#...
-1 -1

output: 2

            1

你会发现核心代码跟上述太大的没有区别,只是我们需要确定节点是“#”才可加入递归中去

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
int n,k,l;
int flag;
const int N =10;
char g[N][N];
bool col[N];
void dfs(int x,int t){
    if(t==k){
      flag++;
      return ;
    }
    if(x==n) return ;
    //不摆放
    dfs(x+1,t);
    //摆放
    for(int i=0;i<n;i++){
      if(g[x][i]=='#'){
        if(!col[i]){
          col[i]=true;
          dfs(x+1,t+1);
          col[i]=false;
        }
      }
    }

}
int main(){
  while(scanf("%d%d",&n,&k)){
    flag=0;
    if(n==-1&&k==-1)break;
    for(int i=0;i<n;i++)
      for(int j=0;j<n;j++){
          cin>>g[i][j];
        }
         dfs(0,0);
         printf("%d\n",flag);
  }
  return 0;
}

      bfs

假设有如上图1这样的迷宫,0为可走,1为墙(别想狗急跳墙了哈),只有上下左右四个方向我们可以走,我们模拟下用bfs如何从左上角到达右下角的路径的,我们从(0,0)点出发,向周围扩展

只有(1,0),从(1,0)这个点再扩展到(2,0),(1,1)下次扩展只有(1,1)可以扩展,扩展到(1,2),从(1,2)就可扩展到(2,2)这时遍历完了。由于每次都是向周围扩展一次,最先到达的不就是我们需要的最短的路径了,这里需要借用数据结构了

int n = 10, m = 10;                   //地图宽高
void BFS()
{
    queue que;              //用队列来保存路口
    int graph[n][m];          //地图
    int px[] = {-1, 0, 1, 0};   //移动方向的数组
    int py[] = {0, -1, 0, 1};
    que.push(起点入队);      //将起点入队
    while (!que.empty()) {    //只要队列不为空
        auto temp = que.pop();          //得到队列中的元素
        for (int i = 0; i != 4; ++i) {
            if(//可以走) {
                //标记当前格子
                //将当前状态入队列,等待下次提取
            }
        }
    } 
}

bfs裸题,给定一个 n×m 的二维整数数组,用来表示一个迷宫,数组中只包含 00 或 11,其中 00 表示可以走的路,11 表示不可通过的墙壁。

最初,有一个人位于左上角 (1,1) 处,已知该人每次可以向上、下、左、右任意一个方向移动一个位置。

请问,该人从左上角移动至右下角 (n,m) 处,至少需要移动多少次。

#include <iostream>
#include <cstring>
#include <queue>
using namespace std;
const int N = 100;
typedef pair<int,int >PII;
int n,m;
int g[N][N];
int d[N][N];//记录到达这个点行走的路程,
PII h[N*N];//数组模拟的队列
int tx[4]={0,1,0,-1};
int  ty[4]={1,0,-1,0};
int bfs(){
    int hh=0,tt=0;
    memset(d,-1,sizeof(d));//初始为-1,也可以区别当前的节点有没有走过
    h[tt]={0,0};
    d[0][0]=0;
    while(tt>=hh){
        auto t=h[hh++];//出队
        for(int i=0;i<4;i++){
            int x=t.first+tx[i],y=t.second+ty[i];
            if(x>=0&&x<n&&y>=0&&y<m&&g[x][y]==0&&d[x][y]==-1){
                d[x][y]=d[t.first][t.second]+1;//向四周扩撒 1
                h[++tt]={x,y};//入队
            }
        }
    }
    return d[n-1][m-1];
}
int main(){
    cin>>n>>m;
    for(int i=0;i<n;i++)
       for(int j=0;j<m;j++)
          cin>>g[i][j];
    cout<<bfs()<<endl;
    return 0;
}

 HDU2717CatchThatCow(BFS很容易理解的例题)

农夫约翰已被告知一头逃亡母牛的位置,并希望立即抓住她。他从数轴上的点N (0 ≤ N ≤ 100,000) 开始,而奶牛在同一数轴上的点K (0 ≤ K ≤ 100,000) 处。Farmer John 有两种交通方式:步行和传送。

* 行走:FJ 可以在一分钟内从X点移动到X - 1 或X + 1点
* 传送:FJ 可以在一分钟内从X点移动到 2 × X点。

如果母牛不知道它的追逐,根本不动,农夫约翰需要多长时间才能取回它?

input :5 17

output: 4

 Farmer John 到达逃亡母牛的最快方式是沿着以下路径移动:5-10-9-18-17,需要 4 分钟。

#include <iostream>
#include <queue>
#include <algorithm>
#include <cstring>
using namespace std;
struct node{
  int x,td;
};
const int N = 100010;
bool map[N];
int n,m;
bool check(int x){
  if(x<0||x>N||map[x])return false;
  return true;
}
int bfs(){
    queue<node>q;
    node t={n,0};
    q.push(t);
    map[n]=true;
    while(q.size()){
      node temp=q.front();
      q.pop();
      if(temp.x==m)return temp.td;
      //状态转移
      if(check(temp.x-1)){
        node e={temp.x-1,temp.td+1};
        map[e.x]=true;
        q.push(e);
      }
      if(check(temp.x+1)){
        node e={temp.x+1,temp.td+1};
        map[e.x]=true;
        q.push(e);
      }
      if(check(temp.x*2)){
        node e = {temp.x*2,temp.td+1};
        map[e.x]=true;
        q.push(e);
      }
    }
}
int main(){
  while(~scanf("%d%d",&n,&m)){
    memset(map,false,sizeof(map));
    int ans=bfs();
    printf("%d\n",ans);
  }
}

3.总结

对于这两个搜索方法,其实我们是可以轻松的看出来,他们有许多差异与许多相同点的。

1.数据结构上的运用

DFS用递归的形式,用到了栈结构,先进后出。

BFS选取状态用队列的形式,先进先出。

2.复杂度

DFS的复杂度与BFS的复杂度大体一致,不同之处在于遍历的方式与对于问题的解决出发点不同,DFS适合目标明确,而BFS适合大范围的寻找。

3.思想

思想上来说这两种方法都是穷竭列举所有的情况。

                  喔噻,看到这里了,可惜没有图可以上了,不然奖励奖励,哈哈哈

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@居安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值