DFS和BFS

二次信任 提交于 2019-12-14 09:11:32

1.油田连通块

链接地址:地址

递归DFS

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
char map[110][110];
bool vis[110][110]={0};//布尔类型减少内存浪费
int orient[8][2]={1,1,1,0,1,-1,0,1,0,-1,-1,1,-1,0,-1,-1};
//八个方向的遍历
int m,n;

void DFS(int x,int y)
{
    if(x<0||x>=m||y<0||y>=n)
        return ;
    if(vis[x][y]==1||map[x][y]!='@')
        return ;
    vis[x][y]=1;

    for(int i=0;i<8;i++)
    {
        DFS(x+orient[i][0],y+orient[i][1]);
    }
}

int main()
{
    while(scanf("%d%d",&m,&n)&&m!=0)
    {
        memset(vis,0,sizeof(vis));
        int count=0;
        for(int i=0;i<m;i++)
            scanf("%s",map[i]);
        for(int i=0;i<m;i++)
            for(int j=0;j<n;j++)
        {
            if(vis[i][j]==0&&map[i][j]=='@')
            {
                DFS(i,j);
                count++;//计数器
            }
        }
        printf("%d\n",count);//不用cout没有追求代码速度,而是追求运行速度
    }
    return 0;
}

2.Knight Moves

链接地址:链接

单向BFS

a.有返回值类型

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
//单向BFS实现,注意队列的使用
bool vis[310][310]={0};
int orient[8][2]={{1,2},{2,1},{-2,1},{-1,2},{-2,-1},{-1,-2},{1,-2},{2,-1}};
int l;
typedef struct node
{
    int x,y,step;
}node;

bool check(int x,int y)
{
    if(x<0||x>=l||y<0||y>=l)
        return false;
    return true;

}
int BFS(int x1,int y1,int x2,int y2)
{
    queue<node>Q;//注意队列的清空
    node temp;
    temp.x=x1,temp.y=y1,temp.step=0;
    Q.push(temp);
    vis[x1][y1]=1;
    while(!Q.empty())
    {
        temp=Q.front();
        Q.pop();
        if(temp.x==x2&&temp.y==y2)//判断弹出条件
            return temp.step;
        for(int i=0;i<8;i++)
        {
            node Next;
            Next.x=temp.x+orient[i][0];
            Next.y=temp.y+orient[i][1];
            Next.step=temp.step+1;
            if(check(Next.x,Next.y)&&vis[Next.x][Next.y]==0)
            {

                vis[Next.x][Next.y]=1;
                Q.push(Next);

            }
        }
    }
    return 0;//欺骗函数的返回,摆设
}
int main()
{
    int t,x1,y1,x2,y2;
    cin>>t;
    while(t--)
    {
        cin>>l;
        cin>>x1>>y1>>x2>>y2;
        memset(vis,0,sizeof(vis));
        printf("%d\n",BFS(x1,y1,x2,y2));


    }
    return 0;
}

b.无返回值类型

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

bool vis[310][310]={0};
int orient[8][2]={{1,2},{2,1},{-2,1},{-1,2},{-2,-1},{-1,-2},{1,-2},{2,-1}};
int l;
typedef struct node
{
    int x,y,step;
}node;

bool check(int x,int y)
{
    if(x<0||x>=l||y<0||y>=l)
        return false;
    return true;

}
void BFS(int x1,int y1,int x2,int y2)
{
    queue<node>Q;
    node temp;
    temp.x=x1,temp.y=y1,temp.step=0;
    Q.push(temp);
    vis[x1][y1]=1;
    while(!Q.empty())
    {
        temp=Q.front();
        Q.pop();
        if(temp.x==x2&&temp.y==y2)
        {
            printf("%d\n",temp.step);//直接进行输出会节省时间
        }
        for(int i=0;i<8;i++)
        {
            node Next;
            Next.x=temp.x+orient[i][0];
            Next.y=temp.y+orient[i][1];
            Next.step=temp.step+1;
            if(check(Next.x,Next.y)&&vis[Next.x][Next.y]==0)
            {

                vis[Next.x][Next.y]=1;
                Q.push(Next);

            }
        }
    }
    //return 0;
}
int main()
{
    int t,x1,y1,x2,y2;
    cin>>t;
    while(t--)
    {
        cin>>l;
        cin>>x1>>y1>>x2>>y2;
        memset(vis,0,sizeof(vis));
        BFS(x1,y1,x2,y2);
    }
    return 0;
}

双向BFS

#include <iostream>
#include<algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
using namespace std;
const int N = 310;
int l;
int vis[N][N];
int dis[N][N];
int orient[8][2]={{1,2},{1,-2},{2,1},{2,-1},{-2,1},{-2,-1},{-1,2},{-1,-2}};
typedef struct node
{
    int x,y;
}node;
void dBFS(int x1,int y1,int x2,int y2)
{
    if(x1==x2&&y1==y2)//注意相等条件的弹出
    {
        printf("0\n");
        return ;
    }
    queue<node>Q;
    node front,behind;//用front,behind是为了复习的时候好理解
    front.x=x1,front.y=y1;
    behind.x=x2,behind.y=y2;
    vis[x1][y1]=1;//从头开始的标记1
    vis[x2][y2]=2;//从尾开始的标记2
    Q.push(front);
    Q.push(behind);
    while(!Q.empty())
    {
        front=Q.front();
        Q.pop();//注意每次的弹出

        for(int i=0;i<8;i++)
        {
            behind.x=front.x+orient[i][0];
            behind.y=front.y+orient[i][1];
            if(behind.x>=0&&behind.x<l&&behind.y>=0&&behind.y<l)//当吧判断条件写成这样可以减少
            {                                                  //进入函数所浪费的时间
                if(!vis[behind.x][behind.y])
                {
                    vis[behind.x][behind.y]=vis[front.x][front.y];
                    dis[behind.x][behind.y]=dis[front.x][front.y]+1;//距离加1,因为队列是
                    Q.push(behind);                                 //先进先出所以是BFS
                }
                else if(vis[behind.x][behind.y]!=vis[front.x][front.y])//最短路径优先输出
                {
                    printf("%d\n",dis[front.x][front.y]+dis[behind.x][behind.y]+1);//相遇时少了一步
                    return;
                }
            }
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(vis,0,sizeof(vis));
        memset(dis,0,sizeof(dis));
        int x1,y1,x2,y2;
        scanf("%d%d%d%d%d",&l,&x1,&y1,&x2,&y2);
        dBFS(x1,y1,x2,y2);

    }
    return 0;

}

3.Red and Black

求定点连通块,直接DFS

链接

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
char map[30][30];
bool vis[30][30];
int w,h,step;
int orient[4][2]={1,0,0,1,-1,0,0,-1};
struct position
{
    int x,y;
};

void DFS(int x,int y)
{
    if(x<0||x>=h||y<0||y>=w||map[x][y]=='#')
        return ;
    if(vis[x][y]!=0)//发现不能用非,一个符号卡了我半小时
        return;
    vis[x][y]=1;
    step=step+1;//计数器
    for(int i=0;i<4;i++)
        {
            DFS(x+orient[i][0],y+orient[i][1]);

        }
}
int main()
{
    while(~scanf("%d%d",&w,&h)&&(w*h)!=0)
    {
        step=0;
        position person;
        memset(map,0,sizeof(map));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<h;i++)
        {
            getchar();//吸掉每次换行的回车,包括第一次输入w,h
            for(int j=0;j<w;j++)
        {
            scanf("%c",&map[i][j]);
            if(map[i][j]=='@')
            {
                person.y=i,person.x=j;//记录人的位置
                //vis[i][j]=1;
            }
        }
        }
        DFS(person.y,person.x);
        printf("%d\n",step);

    }
    return 0;
}

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!