noj:广搜 (bfs) and 深搜(dfs) 整理

一、DFS


1.迷宫问题

Description

Jack和同学在游乐园的迷宫里找不到出路了,请你帮助他们找到正确路线.

Input

迷宫使用0和1字符表示,0表示有路1表示为墙.迷宫为正方形.左上角为(1,1),右下角为(N,N).左上角为入口,出口在(N,N).

输入第一行有3个正整数N,x,y.
N表示迷宫规模,x,y表示Jack和同学所在的迷宫位置. 要求找出从(x,y)到(N,N)的路径( N ≤ 80 ). 且出口和入口的值一定为0

下边为迷宫的字符模型用01表示.

Output

假如找到线路,第一行输出Found下边输出迷宫模型使用´´#´´表示找到的线路.
假如未找到输出Not Found

Sample Input

6 5 2
0 0 1 1 1 1
1 0 0 0 0 1
1 1 1 0 1 1
1 0 0 0 1 1
1 0 1 0 1 1
1 0 1 0 0 0

Sample Output

Found
0 0 1 1 1 1
1 0 0 # # 1
1 1 1 # 1 1
1 0 0 # 1 1
1 0 1 # 1 1
1 0 1 # # #

Hint

1.假定迷宫只有唯一出路,也就是说迷宫内路线宽度不超过2个字符.

Source

NUC
noj.io 1010

solution:

#include<stdio.h>
const int M=81;

int maze[M][M],n;
int dir[][2]={{0,1},{1,0},{0,-1},{-1,0}};

bool dfs(int x,int y)
{
    maze[x][y]=-1;
    for(int i=0; i<4; ++i)
    {
        int nextx=x+dir[i][0];
        int nexty=y+dir[i][1];

        if(nextx==n && nexty==n)
        {
            maze[nextx][nexty]=-1;
            return 1;
        }
        else if(nextx==0||nextx==n+1||nexty==0||nexty==n+1||maze[nextx][nexty]!=0)
            continue;
        else if(dfs(nextx,nexty))
        {
            maze[nextx][nexty]=-1;
            return 1;
        }
    }
    maze[x][y]=0;
    return 0;
}

int main()
{
    int x,y,i,j;
    while(scanf("%d %d %d",&n,&y,&x)!=EOF)
    {
        for(i=1; i<=n; i++)
            for(j=1; j<=n; j++)
                scanf("%d",&maze[i][j]);

        if(dfs(x,y))
        {
            printf("Found\n");
            for(i=1; i<=n; i++)
            {
                for(j=1; j<=n; j++)
                {
                    if(maze[i][j]==-1)
                        printf("# ");
                    else
                        printf("%d ",maze[i][j]);
                }
                printf("\n");
            }
        }
        else
            printf("Not Found\n");
    }
    return 0;
}


给大一同学讲题的时候这题当场没写出来。。。

重写了一遍,感觉当时没有体会到回溯上一行return的意义,把dfs彻底当成brutal了。

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>

using namespace std;

char g[100][100];
int dir[][4] = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
int n;

bool dfs(int x, int y)
{
    if (x == n && y == n)
        return true;
    for (int i = 0; i < 4; i++)
    {
        int nx = x + dir[i][0];
        int ny = y + dir[i][1];
        if (1 <= nx && nx <= n && 1 <= ny && ny <= n && g[nx][ny] == '0')
        {
            g[nx][ny] = '#';
            if (dfs(nx, ny))
                return true;
            g[nx][ny] = '0';
        }
    }
    return false;
}

int main()
{
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
#endif // LOCAL
    int x, y;
    while (scanf("%d%d%d", &n, &y, &x) == 3)
    {
        getchar();
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
            {
                scanf("%c", &g[i][j]);
                getchar();
            }
        }
        g[x][y] = '#';
        if (dfs(x, y))
        {
            printf("Found\n");
            for (int i = 1; i <= n; i++)
            {
                for (int j = 1; j <= n; j++)
                {
                    printf("%c ", g[i][j]);
                }
                printf("\n");
            }
        }
        else
            printf("Not Found\n");
    }
    return 0;
}



2.图的连通性问题

(1).找油田

Description

The GeoSurvComp geologic survey company is responsible for detecting underground oil deposits. GeoSurvComp works with one large rectangular region of land at a time, and creates a grid that divides the land into numerous square plots. It then analyzes each plot separately, using sensing equipment to determine whether or not the plot contains oil. A plot containing oil is called a pocket. If two pockets are adjacent, then they are part of the same oil deposit. Oil deposits can be quite large and may contain numerous pockets. Your job is to determine how many different oil deposits are contained in a grid.

Input

The input contains one or more grids. Each grid begins with a line containing m and n, the number of rows and columns in the grid, separated by a single space. If m = 0 it signals the end of the input; otherwise 1 <= m <= 100 and 1 <= n <= 100. Following this are m lines of n characters each (not counting the end-of-line characters). Each character corresponds to one plot, and is either `*', representing the absence of oil, or `@', representing an oil pocket.

Output

are adjacent horizontally, vertically, or diagonally. An oil deposit will not contain more than 100 pockets.

Sample Input

1 1
*
3 5
*@*@*
**@**
*@*@*
1 8
@@****@*
5 5
****@
*@@*@
*@**@
@@@*@
@@**@
0 0

Sample Output

0
1
2
2

Source

Mid-Central USA 1997
noj.io 1397

solution:

这题让我真正见识到dfs的魅力所在,解决连通性的利刃。

#include<stdio.h>
const int N=101;


int dir[][2]= {{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};
char oil[N][N];
int m,n;

void dfs(int x,int y)
{
    if(oil[x][y]!='@'||x==0||y==0||x==m+1||y==n+1)
        return;
    else
    {
        oil[x][y]='0';
        for(int i=0; i<8; i++)
        {
            dfs(x+dir[i][0],y+dir[i][1]);
        }
    }
}

int main()
{
    int i,j;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        int s=0;
        if(m==0&&n==0)
            break;
        getchar();
        for(i=1; i<=m; i++)
        {
            for(j=1; j<=n; j++)
            {
                scanf("%c",&oil[i][j]);
            }
            getchar();
        }
        for(i=1; i<=m; i++)
        {
            for(j=1; j<=n; j++)
            {
                if(oil[i][j]=='@')
                {
                    dfs(i,j);
                    s++;
                }
            }
        }
        printf("%d\n",s);
    }
    return 0;
    }


(2).找水洼

Description

Due to recent rains, water has pooled in various places in Farmer John's field, which is represented by a rectangle of N x M (1 <= N <= 100; 1 <= M <= 100) squares. Each square contains either water ('W') or dry land ('.'). Farmer John would like to figure out how many ponds have formed in his field. A pond is a connected set of squares with water in them, where a square is considered adjacent to all eight of its neighbors.

Given a diagram of Farmer John's field, determine how many ponds he has.

Input

* Line 1: Two space-separated integers: N and M * Lines 2..N+1: M characters per line representing one row of Farmer John's field. Each character is either 'W' or '.'. The characters do not have spaces between them.

Output

* Line 1: The number of ponds in Farmer John's field.

Sample Input

10 12
W........WW.
.WWW.....WWW
....WW...WW.
.........WW.
.........W..
..W......W..
.W.W.....WW.
W.W.W.....W.
.W.W......W.
..W.......W.

Sample Output

3

Hint

OUTPUT DETAILS: There are three ponds: one in the upper left, one in the lower left,and one along the right side.

Source

USACO 2004 November Gold
noj.io 1158

solution:

同上题思路,稍微修改一下就好了,帅炸了!!
#include<stdio.h>
const int N=101;

int m,n;
char lake[N][N];
int dir[][2]={{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1},{-1,0},{-1,1}};

void dfs(int x,int y)
{
    if(lake[x][y]!='W'||x==0||y==0||x==m+1||y==n+1)
        return;
    else
    {
        lake[x][y]='0';
        for(int i=0; i<8; i++)
        {
            dfs(x+dir[i][0],y+dir[i][1]);
        }
    }
}

int main()
{
    int i,j;
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        int s=0;
        getchar();
        for(i=1; i<=m; i++)
        {
            for(j=1; j<=n; j++)
            {
                scanf("%c",&lake[i][j]);
            }
            getchar();
        }

        for(i=1; i<=m; i++)
        {
            for(j=1; j<=n; j++)
            {
                if(lake[i][j]=='W')
                {
                    dfs(i,j);
                    s++;
                }
            }
        }
        printf("%d\n",s);
    }
    return 0;
}





二、BFS


1.类迷宫

Description

keefo 正在一个迷宫里找宝藏. keefo好不容易找到这个迷宫,这个迷宫传说中藏了不少的宝藏,当然他希望这次能够找出所所有的宝藏. 现在,他已经从杨过那里获得宝藏地图, 现在 keefo 想知道他能够获得多少宝藏.keefo 希望你能够帮他解决这个问题(呵呵~,不是白干哦, keefo会付给你酬金).

现在假设,迷宫是由正方形网格组成 . keefo在迷宫中,只能从 上 ,下,左,右四个方向移动. 但是如果他要走的前方是一堵墙的话,他将不能走过去. 并且,迷宫的四周都是由一堵厚实的墙包围着, 也就是说,keefo不可能走出迷宫之外.

Input

输入包含多组测试数据.

每组测试数据第一行包含两个整形数字, N 和 M ( 1 < N,M ≤ 1000 ), 分别表示迷宫网格的行和列.接下来N行里,每行包含了M个字符.( ´X´ 代表 keefo 当前位置 , ´*´ 代表宝藏 , ´#´代表墙, ´.´ 代表没有任何障碍 ).每个测试数据只包含一个 ´X´ 字符.

Output

输出keefo 能够找到的最多宝藏的个数.

每组数据一行.

Sample Input

4 4
*...
.X..
....
...*

4 4
*#..
#X..
....
...*

Sample Output

2
1

Source

NUC
noj.io 1215

solution:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;
const int N=1001;

char maze[N][N];
int n,m;
int dir[][2]= {{0,1},{1,0},{0,-1},{-1,0}};
bool visit[N][N]= {0};
struct point
{
    int x,y;
};

int bfs(int x,int y)
{
    int s=0;
    memset(visit,0,sizeof(visit));
    queue<point> Q;
    point now,next;
    now.x=x;
    now.y=y;
    Q.push(now);
    visit[now.x][now.y] = 1;

    while(!Q.empty())
    {
        now=Q.front();
        Q.pop();
        for(int i=0; i<4; i++)
        {
            next.x=now.x+dir[i][0];
            next.y=now.y+dir[i][1];

            if(next.x==0||next.y==0||next.x==n+1||next.y==m+1||visit[next.x][next.y])
                continue;

            if(visit[next.x][next.y]==0)
            {
                if(maze[next.x][next.y]=='*')
                {
                    s++;
                visit[next.x][next.y]=1;
                Q.push(next);
                }
                else if(maze[next.x][next.y]=='.')
                {
                    visit[next.x][next.y]=1;
                    Q.push(next);
                }
                else
                {
                    continue;
                }
            }
        }
    }
    return s;
}

int main()
{
    int i,j,x,y;
    while(scanf("%d %d",&n,&m)!=EOF)
    {
        getchar();
        for(i=1; i<=n; i++)
        {
            for(j=1; j<=m; j++)
            {
                scanf("%c",&maze[i][j]);
                if(maze[i][j]=='X')
                {
                    x=i;
                    y=j;
                }
            }
            getchar();
        }
        printf("%d\n",bfs(x,y));
    }
    return 0;
}

2.寻找最短路 and 3D迷宫

Description

你被关进了一个3D的地牢中,现在你需要找到最快的方法迅速的跑出监狱。 地牢是由每一个小方格组成,这些方格可能是墙壁。 假设你每移动一个单位(移动方向,可以是 东, 南, 西 ,北, 上, 下 )需要一分钟的时间。 你不能够沿对角线移动,并且不能够越过地牢,因为地牢四周被坚固的石头包围着。

你能够顺利的从这个地牢中逃脱吗? 你最少需要花多少时间呢?

Input

输入有多组测试数据。

每一个测试数据第一行有三个整形数据 L R 和 C ( L , R, C ≤ 30 )

L 表示地牢的层数 。

R 和 C 分别表示地牢每层的 行数 和 列数 。

接下来的L个地图分别表示地牢的每层地图,每个地图有R行,每行包括C个字符。 每个字符描绘着地牢的每一个小方格,´#´表示墙壁,你不能通过。´.´表示通道 。 并且你的起始地点 和终止分别是 ´S´ 和´E´.

每个地图之间间隔一行。

当L , R , C 均 为 0 时 ,表示输入结束。

Output

每一个测试数据占一行。

如果你能顺利的逃脱,那么请输出:

Escaped in x minute(s).

其中 x 表示 你逃脱所花的最短时间。

如果你不能顺利逃脱,那么请输出:

Trapped!

Sample Input

3 4 5
S....
.###.
.##..
###.#

#####
#####
##.##
##...

#####
#####
#.###
####E

1 3 3
S##
#E#
###

0 0 0

Sample Output

Escaped in 11 minute(s).
Trapped!

Source

NUC
noj.io 1218

solution:

bfs常用来找最短路,不是证明过算导的最短路吗摔,怎么会不记得,第一次用了dfs 。。。wa了摔!!!

而所谓的3D迷宫,无非就是在平面x,y上再立一个z轴,不能斜着走的情况下只有6个方向。

代码:

#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std;

char maze[31][31][31];
int L,R,C;
int xe,ye,ze;
int dir[][3]= {{-1,0,0},{1,0,0},{0,0,1},{0,1,0},{0,0,-1},{0,-1,0}};
bool vis[31][31][31]= {0};

struct point
{
    int x,y,z;
    int num;
};

bool flag;

int bfs(int z,int x,int y)
{
    memset(vis,0,sizeof(vis));

    queue<point> Q;
    point now,next;

    now.z=z;
    now.x=x;
    now.y=y;
    now.num=0;
    Q.push(now);

    while(!Q.empty())
    {
        now=Q.front();
        Q.pop();
        vis[now.z][now.x][now.y]=1;
        for(int i=0; i<6; i++)
        {

            next.z=now.z+dir[i][0];
            next.x=now.x+dir[i][1];
            next.y=now.y+dir[i][2];

            if(vis[next.z][next.x][next.y]||next.z==0||next.y==0||next.x==0||next.z==L+1||next.x==R+1||next.y==C+1||maze[next.z][next.x][next.y]=='#')
                continue;
            if(next.z==ze&&next.x==xe&&next.y==ye)
            {
                flag=1;
                next.num=now.num+1;
                return next.num;
            }
            else if(maze[next.z][next.x][next.y]=='.')
            {
                next.num=now.num+1;
                vis[next.z][next.x][next.y]=1;
                Q.push(next);
            }
        }
    }
}

int main()
{
    int i,j,k,xb,yb,zb,time;
    bool flag1,flag2;
    while(scanf("%d%d%d",&L,&R,&C)!=EOF)
    {
        getchar();
        if(L==0&&R==0&&C==0)
            break;
        flag1=0;
        flag2=0;
        for(i=1; i<=L; i++)
        {
            for(j=1; j<=R; j++)
            {
                for(k=1; k<=C; k++)
                {
                    scanf("%c",&maze[i][j][k]);
                    if(!flag1||!flag2)
                    {
                        if(maze[i][j][k]=='S')
                        {
                            flag1=1;
                            zb=i;
                            xb=j;
                            yb=k;
                        }
                        if(maze[i][j][k]=='E')
                        {
                            flag2=1;
                            ze=i;
                            xe=j;
                            ye=k;
                        }
                    }
                }
                getchar();
            }
            if(i<L)
                getchar();
        }
        flag=0;
        time=bfs(zb,xb,yb);
        if(flag)
            printf("Escaped in %d minute(s).\n",time);
        else
            printf("Trapped!\n");
    }
    return 0;
}



你可能感兴趣的:(noj:广搜 (bfs) and 深搜(dfs) 整理)