首页 > 其他分享 >DFS入门笔记

DFS入门笔记

时间:2024-11-23 17:14:10浏览次数:9  
标签:入门 递归 int void dfs 填入 state DFS 笔记

DFS深度优先搜索-入门 笔记

DFS 依靠递归的思想,总是往更远的方向行进,直到达到边界,再返回到上一步考虑另外的方向

(递归-回溯)

从 \(1\)~\(n\) 这 \(n\) 个整数中随机选取任意多个,输出所有可能的选择方案,即计算\(2^n\)

我们考虑有 \(n\) 个空位,每次都选择填或不填数字进去

同时记录该数字的状态:选择中、填、不填 一共三种状态,所以需要一个数组来存储他们

int n;
int state[20];

然后来构造 dfs 函数:使用 x 这个变量来作为形式参数,意思是当前考虑到了第几个空位

void dfs(int x){
	......
}

此时第 x 位的状态为初始化的 \(0\) ,表示在选择中,每个空位都有两种选择:填或不填

我们把填的状态记作 \(1\) ,不填的状态记作 \(2\)

state[x]=1;//选择填入
dfs(x+1);
state[x]=0;
    
state[x]=2;//选择不填入
dfs(x+1);
state[x]=0;

每次选择填或不填后,再次调用 dfs 递归考虑下一个空位,递归完成后,我们将这一位的状态复位,即state[x]=0回溯

递归到没有空位的情况时,我们就输出方案:

if (x>n){//第x位超过了我们给定的n
    for (int i=1;i<=n;i++){
        if (state[i]==1)//当第i位的状态为1(选了),我们就输出该位填入的数
            printf("%d ",i);
    }
    printf("\n");
    return ;//终止递归,开启回溯
}

完整代码:

#include <stdio.h>

int n;
int state[20];

void dfs(int x){
    
    if (x>n){
        for (int i=1;i<=n;i++){
            if (state[i]==1)
                printf("%d ",i);
        }
        printf("\n");
        return ;
    }
    
    state[x]=1;
    dfs(x+1);
    state[x]=0;
    
    state[x]=2;
    dfs(x+1);
    state[x]=0;
    
}

int main()
{
    scanf("%d",&n);
    dfs(1);
    return 0;
}

从 \(1\)~\(n\) 这 \(n\) 个整数中随机选出 \(m\) 个,输出所有可能的选择方案,即计算\(C_n^m\)

DFS要求我们的方案做到不重不漏,对应组合数的计算,采用“不回头”的策略

还是考虑第 \(x\) 位填不填数字进去,只是需要增加一个参数来记录我们从第几个数开始选数字(不回头)

填第 x 个空位时,我们从第 str 项开始

void dfs(int x, int str){
	......
}

使用for循环来对 n 个数依次进行考虑,定义arr 数组,存储我们的方案

for (int i=str;i<=n;i++){
    arr[x]=i;
    dfs(x+1,i+1);
    arr[x]=0;
}

从 \(1\) 开始考虑,每次填入 arr 数组的第 x 位,然后递归到第 x+1 位,并从第 i+1 项开始选择

最后递归到 x>n 时结束递归,输出arr 数组中每一位填入的数

 if (x>m){
    for (int i=1;i<=m;i++){
        printf("%d ",arr[i]);
    }
    printf("\n");
    return;
}

完整代码:

#include <stdio.h>

int n,m;
int arr[52];

void dfs(int x, int str){
    
    if (x>m){
        for (int i=1;i<=m;i++){
            printf("%d ",arr[i]);
        }
        printf("\n");
        return;
    }
    
    for (int i=str;i<=n;i++){
        arr[x]=i;
        dfs(x+1,i+1);
        arr[x]=0;
    }
}

int main()
{
    scanf("%d %d",&n,&m);
    dfs(1,1);
    return 0;
}

把 \(1\)~\(n\) 这 \(n\) 个整数排成一行后随机打乱顺序,输出所有可能的次序,即计算\(A_n^n\)

我们一样考虑第 \(x\) 位填入数字的操作,但是每次填入的数字都可以取未填过的,因为需要考虑排列顺序

void dfs(int x){
    ......    
}

我们开一个bool数组来记录数字的状态(选过了,未选过)

使用for 循环来遍历所有数字的状态,选择未被使用过的数字填入第 x

for (int i=1;i<=n;i++){
    if (!st[i]){//选择未被使用过的数
        arr[x]=i;
        st[i]=1;//标记该数已被使用
        dfs(x+1);
        st[i]=0;//回溯
    }
}

x>n 即填完了所有空位后,结束递归,输出arr数组记录的填入的数字

if (x>n){
    for (int i=1;i<=n;i++){
        printf("%d ",arr[i]);
    }
    printf("\n");
    return;
}

完整代码:

#include <stdio.h>

int n, arr[10];
bool st[10];

void dfs(int x){
    
    if (x>n){
        for (int i=1;i<=n;i++){
            printf("%d ",arr[i]);
        }
        printf("\n");
        return;
    }
    
    for (int i=1;i<=n;i++){
        if (!st[i]){
            arr[x]=i;
            st[i]=1;
            dfs(x+1);
            st[i]=0;
        }
    }
    
}

int main()
{
    scanf("%d",&n);
    dfs(1);
    return 0;
}

标签:入门,递归,int,void,dfs,填入,state,DFS,笔记
From: https://www.cnblogs.com/dianman/p/18564799

相关文章

  • 现场排查取证溯源简单笔记
    现场排查取证溯源简单笔记自己找资料看的,不确定有没有用首先和客户确定排查范围、方案和方法,不确定的话,可能违法对于主机的入侵痕迹排查,主要从网络连接、进程信息、后门账号、计划任务、登录日志、自启动项、文件等方面进行排查。尽量断网排查,避免受攻击者干扰,也避免攻击者删......
  • 汇编笔记(持续更新中)
    汇编笔记寄存器register​ 学习汇编语言,首先必须了解两个知识点:寄存器和内存模型。​ 先来看寄存器。CPU本身只负责运算,不负责储存数据。数据一般都储存在内存之中,CPU要用的时候就去内存读写数据。但是,CPU的运算速度远高于内存的读写速度,为了避免被拖慢,CPU都自带一级缓存......
  • 动态 DP 学习笔记
    1前言动态DP,简称DDP。用于处理树上带修的简单DP问题。前置知识:树链剖分线段树维护矩阵树形DP2基本做法上模板题:P4719【模板】"动态DP"&动态树分治如果不带修,就是简单的树上DP。设\(f_{i,0}\)表示不选\(i\)点的最大权值,\(f_{i,1}\)表示选\(i\)点并且......
  • 李超线段树学习笔记
    P4097【模板】李超线段树/[HEOI2013]Segment前言李超线段树并不是一种新的线段树,而是对一类题维护最值的过程做了改进,使线段树仍然有不错的复杂度。引入简要题意实现两种操作:在区间\([x_0,y_0]\)上加入一条两端为\((x_0,y_0)\),\((x_1,y_1)\)的线段。查询下标\(k......
  • RabbitMQ2:介绍、安装、快速入门、数据隔离
    欢迎来到“雪碧聊技术”CSDN博客!在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将不断探索Java的深邃世界,分享最新的技术动态、实战经验以及项目......
  • 【大模型智能客服背景下】知识图谱笔记
    【背景】        在数字化飞速发展的时代,客户服务的质量和效率成为企业立足市场、赢得客户信赖的关键因素之一。随着人工智能技术的不断革新,智能客服应运而生,为企业与客户之间搭建起了更为便捷、高效的沟通桥梁。        传统的智能客服系统往往基于预设规则......
  • Unity入门需要学点什么?
    1.核心编程与优化C#高级技能熟练使用C#,掌握面向对象编程、泛型、LINQ、异步编程等。UnityAPI精通深入了解Unity生命周期(例如Awake、Start、Update、FixedUpdate)、事件系统、协程、组件架构。性能优化使用Profiler工具分析和优化性能。减少GC(垃圾回收)压力,优化内存分配。熟......
  • [数据结构笔记]从头插入链表的代码实现
    #仅供个人纪录#小白笔记细致慎入回顾思路:链表实现从头插入需要:结构体头结点结构体指针变量 实现功能的函数主函数(当然)结构体包含:data和指向下一个结构体的指针structNode{intdata;structNode*next;//c++写法可以直接Node*next;};//注意别漏掉;结构指针......
  • 【论文笔记】NeuroLM: a universal multi-task foundation model... (ICLR 2025 Under
    Code:×Data:×目录AbstractIntroductionMethodText-alignedneuraltokenizerMulti-channelautoregressivepre-trainingMulti-taskinstructiontuningResultsDownstreamdatasetsExperimentalresultsAblationonrobustnessAblationoninstructiondatasize......
  • SpringMVC框架---SpringMVC概述、入门案例、常用注解
    目录第一章:三层架构和MVC1.三层架构2.MVC模型第二章:SpringMVC的入门案例1.SpringMVC的简介1.1SpringMVC介绍1.2SpringMVC执行过程2.SpringMVC的入门程序创建WEB工程,引入开发的jar包项目代码3.入门案例的执行过程分析4.RequestMapping注解第三章:请求参数的......