DFS初级总结

一、DFS是什么?

DFS英文全名:Depth First Search;中文名:深度优先算法。DFS是一种早期爬虫使用的常用方法。如今广泛应用于解决数学、游戏等生活问题,例如全排列,组合、迷宫等。

二、原理

DFS原理很简单,举个简单例子。你去找你的同事,他住在一栋5层的房屋里的其中一个房间,但你不知道他在哪个房间,那么你首先就从一楼一个一个房间的找,看他在不在一楼,如果不在一楼,那么就去二楼找。以此类推,你最终会找到他身在哪个房间。这就是DFS的原理(个人拙见)。

三、DFS的使用

1.DFS模板

伪代码如下(示例):

#include<stdio.h>

int check(~~~)
{
	//检查部分
	if~~~return 0;		//不符合要求
	return 1;			//符合要求
}

void dfs(int i)
{
	//判断是否出界
	if(~~~)
	{
		return;
	}
	//填数部分
	for~~~~{
		//检查
		if(!check(~~))
		{
			//代码~~~
			continue;
		}
		//符合要求
		dfs(i+1);
		
		//回溯
		//代码~~~
	}
	return;		//来到这里,dfs搜索结束
}

int main()
{
	dfs(i);		//i代表层数
	return 0;
}

2.使用DFS的几个小例子

(1).全排列
//想必大家高中时期都有学习全排列的知识吧!!!
三个数字(1,2.,3)的全排列有多少种呢?
答案是:321=6种,分别是:123、132、213、231、312、321.
那我们怎么用代码实现呢?话多不说上代码!

#include<iostream>
using namespace std;


int a[3] = { 0 };		//存储数字1、2、3
int target = 0;			//记录排列总数
int k = 0;

bool check(int b) {
	//检查
    int aa = 0;
    for (int i = 0; i < 3; i++) {
        if (a[i] == b) {
        //每次数组中有与b相同的数字时,aa就加1
            aa++;
        }
    }
    //如果aa大于1,就说明不符合要求,
    //即b被使用了两次,也就是说数组
    //a[]中有两个b,返回false
    if (aa > 1) return false;
    return true;

}


void dfs(int k)
{
	//1.跟检查是否越界类似
    if (target == 3) {
    //当target等于3时,说明已经排列完成,
    //我们把它输出
        for (int i = 0; i < 3; i++)
            printf("%d", a[i]);
        printf("\n");
        return;
    }
    //2.填数
    for (int i = 1; i < 4; i++) {
    	//赋值
        a[k] = i;
        if (!check(a[k])) {
        	//不符合要求,我们把它重新赋值为0
            a[k] = 0;
            //并且跳出此次循环
            //这里要注意用的是continue,
            //不要用了return,我第一次写的时候
            //就用了return,结果找了我一下午,
            //希望大家别像我一样啊!!!
            continue;
        }
        target++;	//加一代表数组填数成功,走到这说明前面都成功啦
        dfs(++k);	//接着我们进入下一层

        //回溯,这一段要多多体会哦,不懂就多看几遍!
        k--;
        a[k] = 0;
        target--;
    }
    return;		//dfs搜索结束
}
int main()
{
    dfs(k);
    return 0;
}

运行结果
运行结果

(2).判断素数
我们来找一下1-100中的素数个数。

//2.判断素数+dfs
#include<iostream>
#include<math.h>
using namespace std;

int a[101] = { 1,1 };   //记录100以内(1-100)是素数的数字,赋为0,非素数为1
int k = 2;            //dfs层数标记
int sum = 0;          //记录100以内的素数总数

void dfs(int k) {
    //判断是否出界
    if (k > 100)   return;
    for (int i = 2; i <= sqrt(k); i++)
    {
        if (k % i == 0)  a[k] = 1;
    }
    dfs(++k);
}

int main()
{
    dfs(k);
    for (int i = 0; i < 100; i++)
    {
        if (a[i] == 0) {
            sum++;
            cout << i <<endl;
        }
    }
    cout << endl;
    cout << sum << endl;
    return  0;
}

运行结果
在这里插入图片描述
(3).组合问题
我们选取1-9其中的5个数字的进行排列。

//组合问题(1-10中选出5个组成组合)
#include<iostream>
using namespace std;

int a[5] = { 0 };       //存储由1-9形成的组合
int k = 0;              //dfs层数
int target = 0;         //记录已经排列的数字的数目
int sum = 0;

bool check(int b)
{
    int aa = 0;
    for (int i = 0; i < 5; i++)
    {
        if (a[i] == b) aa++;
        if (aa > 1) return false;
    }
    return true;
}

void dfs(int k)
{
    //判断是否完成组合
    if (target == 5)
    {
        for (int i = 0; i < 5; i++)
        {
            cout << a[i];
        }
        cout << endl;
        sum++;
        return;
    }

    //填数
    for (int i = 1; i < 10; i++)
    {
        a[k] = i;
        if (!check(i))
        {
            a[k] = 0;
            continue;
        }
        target++;
        dfs(++k);

        //回溯
        target--;
        a[k--] = 0;
    }
}


int main()
{
    dfs(k);
    cout << "sum="<<sum;
    return 0;
}

运行结果
在这里插入图片描述

3.升阶DFS使用

我们来提升一下难度,嘻嘻,新手可能会有点难度哦!不多多看几次就行啦!

(1).八皇后
我们就举例一下经典中的经典吧!
题目链接:八皇后题目链接
在这里插入图片描述
代码呈上!!!:

#include<iostream>
using namespace std;

int row[14] = { 0 };
int line[14] = { 0 };
int zhudui[100] = { 0 };
int fudui[100] = { 0 };
int sum = 0;
int i = 1;
int n;

bool check(int i,int j)
{
	//检查是否符合要求
	if (row[j] || zhudui[j - i + n] || fudui[j + i])
	{
		return false;
	}
	return true;
}

void dfs(int i)
{
	//出界并输出
	if (i > n)
	{
		sum++;
		if(sum<=3)
		{ 
			for (int j = 1; j <= n; j++)
			{
				cout << line[j];
			}
			printf("\n");
		}
		return;
	}
	//填数
	for (int j = 1; j <= n; j++)
	{
		if (!check(i, j))
		{
			continue;
		}
		row[j] = 1;
		line[i] = j;
		zhudui[j - i + n] = 1;
		fudui[j + i] = 1;
		dfs(i+1);

		//回溯
		row[j] = 0;
		zhudui[j - i + n] = 0;
		fudui[j + i] = 0;

	}
	return;
}

int main()
{
	cin >> n;
	dfs(i);
	cout << sum << endl;
	return 0;
}

代码运行结果:

在这里插入图片描述

四、总结

dfs的原理很简单、代码也很简洁,但是其中蕴含的内容却对新人来说有点绕,我们需要多多理解、多多整理思路。如果你想成为算法大师,这是必过的一道坎!加油吧!程序猿!!!

五、最后

这是我第一次写CSDN,有不对的地方希望大家多多包涵!有问题可以告诉我。希望这篇文章对大家能有所帮助。谢谢啦!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个有梦想的懒人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值