简单的dfs

dfs(Depth_First_Search):

它是一种图的遍历形式,其具体意义是从图中的某个顶点v出发,不停的遍历v的各个临界点,然后从各个临界点开始继续的向四周发散,直至遍历完所有与v路径相通的点,究其本质其实是应用了一种递归的思想;

模板代码为:

void dfs()//参数用来表示状态
{
    if(到达终点状态)
    {
        ...//根据题意添加
        return;
    }
    if(越界或者是不合法状态)
        return;
    if(特殊状态)//剪枝
        return ;
    for(扩展方式)
    {
        if(扩展方式所达到状态合法)
        {
            修改操作;//根据题意来添加
            标记;
            dfs();
            (还原标记);
            //是否还原标记根据题意
            //如果加上(还原标记)就是 回溯法
        }  

    }
} 

对于dfs来说简单的应用有全排列,迷宫问题,或者结合剪枝,回溯,dp等算法;下面我们来介绍其具体应用;

1.dfs全排列问题:

#include<iostream>
#include<string.h>
using namespace std;
int a[101],b[101];
int i,j,n;
void  print()
{
    for(i=1;i<=n;i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}
void dfs(int i)
{
    if(i==n+1)
    {
        print();
        return ;
    }
    for(int j=1;j<=n;j++)//int j是每一次都赋值,而j,则在递归过程中也会继续++;
    {
        if(b[j]==0)
        {
            a[i]=j;
            b[j]=1;
            dfs(i+1);
            b[j]=0;
        }
    }
}
int main()
{
    cin>>n;
    memset(a,sizeof(a),0);
    memset(b,sizeof(b),0);
    dfs(1);
    return 0;
}

全排列问题就是一种典型的dfs问题,由于需要遍历所有的数字,而且不能重复,因而与dfs的不断发散的主题刚好契合,当然对于c++来说next_permutation是更简单的一种全排列,同时这种全排列的解决方法还可以与回溯法相结合解决典型的

n皇后问题:
n皇后的问题关键是所有的位置既不能同行,也不能同列,还不可以同对角线,比如第一行的第一列放棋子,下一行就只能在二至n列放置棋子同时需要减去对角线上的情况,即为n*(n-1)*(n-2)...*1再减去对角线上的情况,其实只是上题的代码加上一个判断条件:if(abs(pre[x]-x)==abs(pre[y]-y))return false;

void generate(int index)
{
    if(index==n+1)
    {
        res++;
        return;
    }
    for(int x=1;x<=n;x++)
    {
        if(hashTable[x]==true)//此行没下子;
        {
            bool flag=true;
            for(int pre=1;pre<index;pre++)
            {
                if(abs(P[pre]-x)==abs(pre-index))
                {
                    flag=false;
                    break;
                }
            }
            if(flag)
            {
            P[index]=x;
            hashTable[x]=true;
            generate(index+1);//继续下一列;
            hashTable[x]=false;//此次排列结束,回溯;
            }
        }
    }
}

3.迷宫类问题:对于迷宫类问题来说,若是求所有的可行路径就采用dfs,而求最短路径则bfs更加简便;

解决迷宫问题实际就是图的遍历思想,一步一步的发散寻路,到达一次终点res++,最终可以得到所有的路径。

题目:
从s到t,.意味着可以走,*意味着不能走,如果能走,输出路径,如果不能走,输出no

输入:

5 6
....S*
.***..
.*..*.
*.***.
.T....

输出:

....m*
.***mm
.*..*m
*.***m
.Tmmmm  

解决代码:

#include <iostream>
#include <string>
using namespace std;
int n, m;
string maze[110];
bool vis[110][110];
bool in(int x,int y){//防止走到地图外面
    return 0<=x&&x<n&&0<=y&&y<m;
}
bool dfs(int x,int y){//x代表行,y代表列
    if(maze[x][y]==‘T‘){
        return true;
    }
    vis[x][y]=1;//标记当前点已走过
    maze[x][y]=‘m‘;//走过的点用字符m标记
    int tx = x-1,ty=y;//向上搜
    if(in(tx,ty)&&maze[tx][ty]!=‘*‘&&!vis[tx][ty]){
        if(dfs(tx,ty)){
            return true;
        }
    }
    tx=x,ty=y-1;//左
    if(in(tx,ty)&&maze[tx][ty]!=‘*‘&&!vis[tx][ty]){
        if(dfs(tx,ty)){
            return true;
        }
    }
    tx=x+1,ty=y;//下
    if(in(tx,ty)&&maze[tx][ty]!=‘*‘&&!vis[tx][ty]){
        if(dfs(tx,ty)){
            return true;
        }
    }
    tx=x,ty=y+1;//右
    if(in(tx,ty)&&maze[tx][ty]!=‘*‘&&!vis[tx][ty]){
        if(dfs(tx,ty)){
            return true;
        }
    }
    vis[x][y]=0;
    maze[x][y]=‘.‘;
    return false;
}
int main() {
    // 输入迷宫地图
    cin >> n >> m;
    for (int i = 0; i < n; i++) {
        cin >> maze[i];
    }
    int x,y;//确定起始位置
    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            if(maze[i][j]==‘S‘){
                x=i,y=j;
            }
        }
    }
    if(dfs(x,y)){
        for(int i=0;i<n;++i){
            cout<<maze[i]<<endl;
        }
    }
    else{
        cout<<"NO!"<<endl;
    }
    return 0;
}

但一般迷宫问题并不会出现DFS,因为对于迷宫问题来说有太多的不必要的走法需要记录,例如在i+1步到迷宫边界,那么回溯一步,继续向别处走也是一种迷宫的走法,一般DFS在迷宫中主要用于在BFS算法进行求解最短路径时,输出最短路的路径;

 void dfs(int x, int y) //递归打印
{
    if (x == 0 && y == 0)return;
    dfs(father[x][y].x, father[x][y].y);
//cout<<father[x][y].dir;
cout<<father[x][y].dir<<father[x][y].x<<father[x][y].y<<endl;;
}

原文地址:https://www.cnblogs.com/lszz/p/11827027.html

时间: 2024-07-30 16:35:53

简单的dfs的相关文章

UVA 572(简单的dfs)

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

kb-01-a&lt;简单搜索--dfs八皇后问题变种&gt;

题目描述: 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. Input 输入含有多组测试数据. 每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目. n <= 8 , k <= n 当为-1 -1时表示输入结束. 随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示棋盘区域,

poj 1321 棋盘问题 (简单的DFS)

棋盘问题 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 26726   Accepted: 13242 Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. Input 输入含有多组测试数据. 每组数据的第一行是两个正整数,n k,用一个空格隔开,表示

蓝桥杯 历届试题 剪格子 简单的DFS~~注意输入有陷阱~~

历届试题 剪格子 时间限制:1.0s   内存限制:256.0MB 问题描述 如下图所示,3 x 3 的格子中填写了一些整数. +--*--+--+ |10* 1|52| +--****--+ |20|30* 1| *******--+ | 1| 2| 3| +--+--+--+ 我们沿着图中的星号线剪开,得到两个部分,每个部分的数字和都是60. 本题的要求就是请你编程判定:对给定的m x n 的格子中的整数,是否可以分割为两个部分,使得这两个区域的数字和相等. 如果存在多种解答,请输出包含左上

棋盘问题 简单搜索DFS

Description 在一个给定形状的棋盘(形状可能是不规则的)上面摆放棋子,棋子没有区别.要求摆放时任意的两个棋子不能放在棋盘中的同一行或者同一列,请编程求解对于给定形状和大小的棋盘,摆放k个棋子的所有可行的摆放方案C. Input 输入含有多组测试数据. 每组数据的第一行是两个正整数,n k,用一个空格隔开,表示了将在一个n*n的矩阵内描述棋盘,以及摆放棋子的数目. n <= 8 , k <= n 当为-1 -1时表示输入结束. 随后的n行描述了棋盘的形状:每行有n个字符,其中 # 表示

《挑战》2.1 POJ 2386 Lake Counting (简单的dfs)

1 # include<cstdio> 2 # include<iostream> 3 4 using namespace std; 5 6 # define MAX 123 7 8 char grid[MAX][MAX]; 9 int nxt[8][2] = { {1,0},{0,-1},{-1,0},{0,1},{1,1},{1,-1},{-1,1},{-1,-1} }; 10 int n,m; 11 12 int can_move( int x,int y ) 13 { 14

Strange Country II ( 简单的dfs,但是要注意细节)

Strange Country II You want to visit a strange country. There are n cities in the country. Cities are numbered from 1 to n. The unique way to travel in the country is taking planes. Strangely, in this strange country, for every two cities A and B, th

《挑战》2.1 POJ POJ 1979 Red and Black (简单的DFS)

B - Red and Black Crawling in process... Crawling failed Time Limit:1000MS     Memory Limit:30000KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 1979 Description There is a rectangular room, covered with square tiles. Each tile is col

Codeforces Round #595 (Div. 3)B2 简单的dfs

原题 https://codeforces.com/contest/1249/problem/B2 这道题一开始给的数组相当于地图的路标,我们只需对每个没走过的点进行dfs即可 #include <bits/stdc++.h> using namespace std;const int maxn=2e5+20;int a[maxn],b[maxn],c[maxn];int dfs(int pos,int step){//传递坐标与步数 if(b[pos]==1){//再次遇到b[pos],返回