欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

BFS 题目 总结

程序员文章站 2022-06-12 09:14:45
...

首先介绍 一下BFS 和 DFS 之间的区别 

首先 上图

BFS 题目 总结

 

         这个图 如果 用 DFS 搜索的应该是 从 根节点 1 开始 然后沿着 从左向右 将 每个分支 搜索到底 比如 搜索到 5这个节点时

 就是 5-->9 然后回去 再 5-->10 -->14再回去 10-->15 再回去 将每个分支搜索完毕 

         用 BFS的话 也是 从 更节点开始搜索但是 BFS 要 通过  一个叫队列 的 东西

        队列 是一个先进先出的类似于数组的数据结构 但是是很简单 的    

        queue<数据类型>变量名    这就是一个简单的定义   

      BFS的搜索顺序 是将 靠近这个节点且距离相等的点 搜索完毕  这里需要标记一下 该节点是否在队列里面 这个图的搜索顺序是从1开始 然后依次到达 15;

      接下来是几个例题 关于BFS的 

     第一个   PO 2251  点这里  http://poj.org/problem?id=2251

     这是一个 有六条路径的类似于迷宫的BFS

Source Code

Problem: 2251		User: rg180120
Memory: 856K		Time: 47MS
Language: G++		Result: Accepted
Source Code
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;

struct Node
{
    int x,y,z;
    int len;
};

Node c,d;

char a[35][35][35];
int b[35][35][35];
int L,R,C;

int f[3][6]={{1,-1,0,0,0,0},
            {0,0,1,-1,0,0},
            {0,0,0,0,1,-1}};

int s2[35][35][35];
int flag;
int si,sj,sk;

bool pop(int x,int y,int z)
{
    return (x>=1&&x<=L&&y>=1&&y<=R&&z>=1&&z<=C);
}

int bfs(int si,int sj,int sk)
{
    queue<Node>s;
    c.x=si;
    c.y=sj;
    c.z=sk;
    c.len=0;
    s.push(c);
    while(!s.empty())
    {
        d=s.front();
        s.pop();
        c.len=d.len+1;
        for(int i=0;i<6;i++)
        {
            c.x=d.x+f[0][i];
            c.y=d.y+f[1][i];
            c.z=d.z+f[2][i];
            if(pop(c.x,c.y,c.z)&&!b[c.x][c.y][c.z]&&a[c.x][c.y][c.z]!='#')
            {
                if(a[c.x][c.y][c.z]=='E')
                    return c.len;
                b[c.x][c.y][c.z]=1;
                s.push(c);
            }
        }
    }
    return -1;
}


int main()
{
    while(cin>>L>>R>>C)
    {
        if(!L&&!R&&!C)  break;
        memset(b,0,sizeof(b));
        for(int i=1;i<=L;i++)
        {
            for(int j=1;j<=R;j++)
            {
                for(int k=1;k<=C;k++)
                {
                    cin>>a[i][j][k];
                    if (a[i][j][k]=='S')
                    {
                        si=i;
                        sj=j;
                        sk=k;
                    }
                }
            }
        }
        flag=bfs(si,sj,sk);
        if (flag==-1)
            cout << "Trapped!" << endl;
        else
             cout << "Escaped in " << flag << " minute(s)." << endl;

    }
    return 0;
}

          下一道    点这里 POJ3278    http://poj.org/problem?id=3278

          这道题目的意思是 从N 点到K点   可以 通过向前一步 即为在这个数轴上加一 还有向后一步 即为减一 
还有一个是向前走到2倍的位置如 从4到8  ,这三种方式每进行一步耗时都为一秒, 怎么通过这三种方式到达K点最快 

Source Code

Problem: 3278		User: rg180120
Memory: 1512K		Time: 32MS
Language: G++		Result: Accepted
Source Code
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<cstdio>
using namespace std;

const int maxn=100000;

typedef long long ll;


int n,k;
int ans;
int vis[maxn+7];
int dis[maxn+7];
queue<int>s;

int bfs(int n)
{
    int head,next;
    s.push(n);
    dis[n]=0;
    vis[n]=1;
    while(!s.empty())
    {
        head=s.front();
        s.pop();
        for(int i=1;i<=3;i++)
        {
            if(i==1)
                next=head+1;
           else if(i==2)
                next=head-1;
           else if(i==3)
                next=head*2;
            if(next<0 || next>maxn) continue; //排除出界情况
            if(!vis[next])
            {
                vis[next]=1;
                dis[next]=dis[head]+1;
            
                s.push(next);
            }
        
            if(next==k)
                return dis[next];
        }
    }
    return -1;
}

int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,0,sizeof(dis));
        while(!s.empty()) s.pop();
        ans=bfs(n);
        cout<<ans<<endl;
    }
}

再来一道 POJ 1426 http://poj.org/problem?id=1426

 

这道题目 是非常有意思的题目  意思大体是说 给你一个数 找到 这个数的一个倍数光有1和0组成 答案有多个 每个数输出一个 就行  这道题 一上来看起来和BFS没大有关系 然后你仔细 想  是不是 相当于 从1开始的有两条路一个是*10一个数是*10+1;那么这样

就是一个典型的BFS题目的 代码是非常简单的

Source Code

Problem: 1426		User: rg180120
Memory: 5000K		Time: 438MS
Language: G++		Result: Accepted
Source Code
#include<cstdio>
#include<iostream>
#include <algorithm>
#include<queue>
using namespace std;

typedef long long ll;

queue<ll>s;
ll d;
ll temp1,temp2;
int n;

void bfs()
{
    s.push(1);
    while(!s.empty())
    {
        d=s.front();
        s.pop();
        if(d%n==0)
        {
            cout<<d<<endl;
            return ;
        }
        else
        {
            temp1=d*10;
            temp2=d*10+1;
            s.push(temp1);
            s.push(temp2);
        }
    }
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)    break;
        bfs();
        while(!s.empty())   s.pop();

    }
    return 0;
}

还有一个 POJ 3126 http://poj.org/problem?id=3126

 

          这道题目 是说 给你一个T;表示有T组输入 然后 每组两个4位数的素数的数据 N,,M; 意思是 将N变成M每次 只能改变一位数且每次改变位到应该是素数然后从N最短需要几步到M  首先对这个题目需要先打表 主要将 1000到10000的素数标记出来 

然后分别对每位数据进行 操作 

Source Code

Problem: 3126		User: rg180120
Memory: 764K		Time: 16MS
Language: G++		Result: Accepted
Source Code
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;

typedef long long ll;
const int maxn=10030;


struct Node
{
    int date;
    int len;
};


int t,n,m;
int vis[maxn+7];
int isprime[maxn+7];


void prime()
{
    memset(isprime,0,sizeof(isprime));
    for(int i=2;i<=maxn;i++)
    {
        if(!isprime[i])
        for(int j=i*2;j<=maxn;j+=i)
            isprime[j]=1;
    }
}


Node w,l;
queue<Node>q;


void bfs(int n,int m)
{

    vis[n]=1;
    l.date=n;
    l.len=0;
    q.push(l);
    while(!q.empty())
    {
        l=q.front();
        q.pop();
       // cout<<l.date<<endl;
        if(l.date==m)
        {
            cout<<l.len<<endl;
            return ;
        }
        for(int i=1;i<=9;i++)  //个
        {
            int s=l.date/10*10+i;
            if(!vis[s]&&!isprime[s])
            {
                vis[s]=1;
                w.date=s;
                w.len=l.len+1;
                q.push(w);
            }

        }
        for(int i=0;i<=9;i++)   //十
        {
            int s=l.date/100*100+l.date%10+i*10;
            if(!vis[s]&&!isprime[s])
            {
                vis[s]=1;
                w.date=s;
                w.len=l.len+1;
                q.push(w);
            }
        }
        for(int i=0;i<=9;i++)   //百
        {
            int s=l.date/1000*1000+l.date%100+i*100;
            if(!vis[s]&&!isprime[s])
            {
                vis[s]=1;
                w.date=s;
                w.len=l.len+1;
                q.push(w);
            }
        }
        for(int i=1;i<=9;i++) //千
        {
            int s=l.date%1000+i*1000;
            if(!vis[s]&&!isprime[s])
            {
                vis[s]=1;
                w.date=s;
                w.len=l.len+1;
                q.push(w);
            }
        }
    }
   // cout<<"Impossible"<<endl;
}


int main()
{
    cin>>t;
    prime();
    while(t--)
    {
        cin>>n>>m;
        while(!q.empty())   q.pop();
        memset(vis,0,sizeof(vis));
        bfs(n,m);
    }
    return 0;
}