c语言 DFS算法 递归调用

深度优先搜索属于图算法的一种,英文缩写为DFS即Depth First Search.

其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次

深度优先算法DFS

模型(以二维直角坐标来举例)

void dfs(int dep) dep表示深度 

{

    判断边界,如果到了边界返回

    尝试每一种可能结果for(i=0;i<n;i++)

    {

        处理当前步

        继续下一步dfs(dep + 1)

    }

    return ;

}

具体实现伪代码 

const int maxn=100;
bool vst[maxn][maxn]; // 访问标记
int map[maxn][maxn]; // 坐标范围
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量,(x,y)周围的四个方向


bool CheckEdge(int x,int y) // 边界条件和约束条件的判断
{
if(!vst[x][y] && ...) // 满足条件
return 1;
else // 与约束条件冲突
return 0;
}


void dfs(int x,int y)
{
vst[x][y]=1; // 标记该节点被访问过
if(map[x][y]==G) // 出现目标态G
{
...... // 做相应处理
return;
}
for(int i=0;i<4;i++)
{
if(CheckEdge(x+dir[i][0],y+dir[i][1])) // 按照规则生成下一个节点
dfs(x+dir[i][0],y+dir[i][1]);
}
return; // 没有下层搜索节点,回溯
}
int main()
{
......
return 0;
}*

例题1:方格分割(第八届蓝桥杯省赛题目)

6×6的方格,沿着格子的边线剪开成两部分。

要求这两部分的形状完全相同。

如图:p1.png, p2.png, p3.png 就是可行的分割法。

试计算:

包括这3种分法在内,一共有多少种不同的分割方法。

注意:旋转对称的属于同一种分割法。

请提交该整数,不要填写任何多余的内容或说明文字。

思路:

可以用分割格子的线来求,因为线也是关于(3,3)点对称的,

所以可以初始化从点(3,3)开始用深搜同时走对称的两条线。 

因为旋转对称属于同一种分法,所以求得的结果除以4即是答案*/

#include<bits/stdc++.h>
using namespace std;
int dir[4][2] = {0,1, 0,-1, 1,0, -1,0};	 //定义一个二维数组来存放搜索方向 
const int maxn=8;						 
int vis[maxn][maxn];  
int ans = 0;  							//ans统计次数 
void dfs(int x, int y)
{  
    if(x == 0 || y == 0 || x == 6 || y == 6)
	{  
        ans++;  
        return ;  
    }  
    for(int i = 0; i < 4; i++)
	{  
        int x1 = x + dir[i][0];  
        int y1 = y + dir[i][1];  
          
        int x2 = 6 - x1;  
        int y2 = 6 - y1;  
          
        if(x1 >= 0 && y1 >= 0 && x1 <= 6 && y1 <= 6)
		{  
            if(!vis[x1][y1])			//逻辑取反 
			{  
                vis[x1][y1] = vis[x2][y2] = 1;  
                dfs(x1,y1);  
                vis[x1][y1] = vis[x2][y2] = 0;  
            }  
        }  
    }  
}  
  
  
int main(){  
    memset(vis, 0, sizeof(vis));  //vis数组初始化0的快捷方法 
    vis[3][3] = 1;  
    dfs(3,3);  
    printf("%d\n",ans/4);  
      
    return 0;  
}  

例题2:

【问题描述】

小明最近喜欢搭数字积木。一共有10块积木,每个积木上有一个数字,0~9。

搭积木规则:

每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小。

最后搭成4层的金字塔形,必须用完所有的积木。

0

1 2

3 4 5

6 7 8 9
请你计算这样的搭法一共有多少种?

#include<stdio.h>
#include<stdlib.h>


int visited[10]={0};                            //查看该元素是否被访问   全部赋值为0 
int a[10]={0,1,2,3,4,5,6,7,8,9};
int sum=0;                                      //定义全局变量sum来进行对符合条件的组合计数


int test(int n){                                //判断基本符合条件 
    if(n==2){					//当三个积木 第二层时 
        if(a[0]<a[1]&&a[0]<a[2]){
            return 1;   
        }
        return 0;
    }
    else if(n==5){				    //六个积木 第三层时 
        if(a[1]<a[3]&&a[1]<a[4]&&a[2]<a[4]&&a[2]<a[5]){
            return 1;
        }
        return 0;
    }
    else if(n==9){				//10个积木 第四层时 
        if(a[3]<a[6]&&a[3]<a[7]&&a[4]<a[7]&&a[4]<a[8]&&a[5]<a[8]&&a[5]<a[9]){
            sum++;
            return 1;
        }
        return 0;
    }
    else
        return 1;
}


void dfs(int n){
    int i;
    for(i=0;i<10;i++){
        if(!visited[i]){		//如果不对则visited[i]=0 
            visited[i]=1;		//visited赋值为1 代表已经访问 
            a[n]=i;
            if(!test(n)){		//如果test[n]=0  则表示不符合条件 
                visited[i]=0;		
                continue;
            }
            dfs(n+1);
            visited[i]=0;
        }
    }
}


int main(){
    dfs(0);
    printf("%d\n",sum);
    return 0;
}

    原文作者:DFS
    原文地址: https://blog.csdn.net/qq_38663663/article/details/79715908
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞