深度优先搜索

warning: 这篇文章距离上次修改已过1006天,其中的内容可能已经有所变动。

理解深度优先搜索的关键在于解决“当下该如何做”。至于“下一步该如何做”则与“当下该如何做”是一样的。
基本模型:

void dfs(int step)
{
    判断边界
    尝试每一种可能 for(i=1;i<=n;i++)
    {
       继续下一步 dfs(step+1)
    }
    返回
}
//或者是
int dfs(int t)
{
    if(满足输出条件)
    {
        输出解;
    }
    for(int i=1;i<=尝试方法数;i++)
        if(满足进一步搜索条件)
        {
            为进一步搜索所需要的状态打上标记;
            dfs(t+1);
            恢复到打标记前的状态;//也就是说的{回溯一步}
        }
}

示例1:输入整数n,全排列1~n

#include "stdio.h"
int a[10],book[10],n;
void dfs(int step){
    int i; 
    if(step==n+1){
        for(i=1;i<=n;i++){
            printf("%d",a[i]);
        }
        printf("\n");
        return;
    }
    for(i=1;i<=n;i++){
        if(book[i]==0){
            a[step]=i;
            book[i]=1;
            dfs(step+1);
            printf("\n");
            book[i]=0;
        }
    
    }
    return;
}
int main(){
    scanf("%d",&n);
    dfs(1);
    return 0;
}

示例2:□ □ □ + □ □ □ = □ □ □,在□中填入1~9使等式成立且每位数字只出现一次

#include "stdio.h"
int a[10],book[10],sum=0;
void dfs(int step){
    int i;
    if(step==10){
        if(a[1]*100+a[2]*10+a[3]+a[4]*100+a[5]*10+a[6]==a[7]*100+a[8]*10+a[9]){
            sum++;
            printf("%d%d%d+%d%d%d=%d%d%d ",a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]); 
        }
        return;
    }
    for(i=1;i<=9;i++){
        if(book[i]==0){
            a[step]=i;
            book[i]=1;
            dfs(step+1);
            book[i]=0;
        }
    }
    return;
}
int main(){
    dfs(1);
    printf("\n");
    printf("一共有%d组结果",sum/2);
}

示例3:迷宫。
给定一个N*M方格的迷宫,迷宫里有T处障碍,障碍处不可通过。给定起点坐标和终点坐标,问: 每个方格最多经过1次,有多少种从起点坐标到终点坐标的方案。在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。

#include "stdio.h"
int m,n,p,q,min=99999,sum=0;
int a[51][51],book[51][51];
void dfs(int x,int y,int step){
    int next[4][2]={
    {0,1},//向右走 
    {1,0},//向下走
    {0,-1},//向左走
    {-1,0}};//向上走
    int tx,ty,k;
    //判断是否到达位置 
    if(x==p&&y==q){
        if(step<min){
            sum++;
            min=step;
        }
        return;//很重要 
    }
    //枚举4种走法 
    for(k=0;k<=3;k++){
        //计算下一个点坐标 
        tx=x+next[k][0];
        ty=y+next[k][1];
        //判断是否越界 
        if(tx<1||tx>n||ty<1||ty>n){
            continue;
        }
        //判断该点是否为障碍物或已经在走过的路径中 
        if(a[tx][ty]==0&&book[tx][ty]==0){
            book[tx][ty]=1;
            dfs(tx,ty,step+1);
            book[tx][ty]=0;
        }
    }
    return ; 
}
int main(){
    int i,j,startx,starty;
    scanf("%d %d",&n,&m);//n行m列
    //读入迷宫 
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
        }
    }
    //读入起止点坐标
    scanf("%d %d %d %d",&startx,&starty,&p,&q);
    //从起始点开始搜索
    book[startx][starty]=1;
    dfs(startx,starty,0);
    printf("共有%d条路径",sum)
    printf("\n");
    printf("最短路径走了%d步",min);
    return 0;  
}

添加新评论