ACM搜索专题(BFS,DFS,记忆化搜索等)

本次的搜索专题的题目来源主要有 洛谷vjudege 上的搜索专题

一.BFS

1. 01迷宫

题目链接:https://www.luogu.org/problemnew/show/P1141
题目分析:这个题算是一个入门级的BFS搜索,题目中所需要的输出就是从一个格子可以最多走多少个格子,格子不能重复。
这个题使用BFS,DFS都可以,我先来讲一下BFS的做法
这个题就是一个带方向的搜索,为了方便搜索,我们设置两个数组分别存储方向。

因为每一个点都有x,y两个坐标,所以这里我使用一个结构体保存每一个点

struct node
{
    int x,y;
};

可以看到这个题的m的取值还是很大的,如果不保留状态,每一次都重新搜索肯定会超时,所以这里我使用一个数组保存计算过的点的格数,采用记忆化搜索

int b[1000005][2];        //记录搜索过的点
int f[1001][1001];         //存储每个点对应的答案

接下来是完整的代码

#include<bits/stdc++.h>
using namespace std;
char Map[1001][1001];       //存放整个图,为了节省空间这里使用字符型
int vis[1001][1001];       //记录点的状态
int b[1000005][2];        //记录搜索过的点
int f[1001][1001];         //存储每个点对应的答案
int v_x[4]={1,-1,0,0};
int v_y[4]={0,0,1,-1};
int num;
int n,m;
struct node
{
    int x,y;
};
void bfs(int x,int y)
{
    queue<node>qu;
    node a1,a2;
    a1.x=x;a1.y=y;
    num++;
    b[num][0]=x;
    b[num][1]=y;
    vis[x][y]=1;
    qu.push(a1);
    while (!qu.empty()) {
        node a=qu.front();
        qu.pop();
        for (int i=0; i<4; i++) {
            int nx=a.x+v_x[i],ny=a.y+v_y[i];
            a2.x=nx;a2.y=ny;
            if (vis[nx][ny]==0&&Map[a.x][a.y]!=Map[nx][ny]&&nx>0&&nx<=n&&ny>0&&ny<=n) {
                num++;
                vis[nx][ny]=1;
                b[num][0]=nx;
                b[num][1]=ny;
                qu.push(a2);
            }
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++) {
        scanf("%s",Map[i]+1);
    }
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=n; j++) {
            if (vis[i][j]==0) {
                bfs(i,j);
                for (int i=1; i<=num; i++) {
                    f[b[i][0]][b[i][1]]=num;
                }
                num=0;
            }
        }
    }
    while (m--) {
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",f[x][y]);
    }
    
}

这个题里我使用了c++的队列,在C中需要自己写,这也是在做算法竞赛的时候使用c++快捷的一个理由吧,需要了解更多的同学可以去看下c++的STL标准库。
因为我使用了一个数组存储遍历过的点的格数,所以我只需要遍历一遍,然后不断的输入m,输出对应的值即可,也就是这段代码

  for (int i=1; i<=n; i++) {
        for (int j=1; j<=n; j++) {
            if (vis[i][j]==0) {
                bfs(i,j);
                for (int i=1; i<=num; i++) {
                    f[b[i][0]][b[i][1]]=num;
                }
                num=0;
            }
        }
    }
    while (m--) {
        int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",f[x][y]);
    }

接下来是使用DFS的做法,代码会简洁很多

char Map[1001][1001];
int b[1000005][2];
int f[1001][1001];
int vis[1001][1001];
int v_x[4]={1,-1,0,0};
int v_y[4]={0,0,1,-1};
int n,m;
int num;
void dfs(int x,int y)
{
    num++;
    vis[x][y]=1;
    b[num][0]=x;
    b[num][1]=y;
    for (int i=0; i<4; i++) {
        int fx=x+v_x[i];
        int fy=y+v_y[i];
        if (fx>0&&fx<=n&&Map[fx][fy]!=Map[x][y]&&!vis[fx][fy]&&fy>0&&fy<=n) {
            dfs(fx, fy);
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1; i<=n; i++) {
        scanf("%s",Map[i]+1);
    }
    for (int i=1; i<=n; i++) {
        for (int j=1; j<=n; j++) {
            if (!vis[i][j]) {
                dfs(i, j);
                for (int t=1; t<=num; t++) {
                    f[b[t][0]][b[t][1]]=num;
                }
                num=0;
            }
        }
    }
    while (m--) {
        int a,b;
        scanf("%d%d",&a,&b);
        printf("%d\n",f[a][b]);
    }
}

posted @ 2019-04-04 20:56  SEC.VIP_网络安全服务  阅读(204)  评论(0编辑  收藏  举报