当前位置: 首页 > news >正文

DFS深度优先搜索

DFS是一种暴力的搜索,其核心思想是遍历所有方案,一条路走到黑再进行回溯。存储时只需要存储路径。

例1:按字典序输出1-n的全排列。

这就要求我们做到前面已经用过的数字不再出现,因此我们需要一个state数组来去重并且在回溯时恢复现场。

int path[N];//保存序列
int state[N];//数字是否被用过
int n;
void dfs(int u)//u代表当前的层数
{
    if(u > n)//数字填完了,输出
    {
        for(int i = 1; i <= n; i++)//输出方案
            cout << path[i] << " ";
        cout << endl;
        return ;
    }

    for(int i = 1; i <= n; i++)//空位上可以选择的数字为:1 ~ n
    {
        if(!state[i])//如果数字 i 没有被用过
        {
            path[u] = i;//放入空位
            state[i] = 1;//数字被用,修改状态
            dfs(u + 1);//填下一个位
            state[i] = 0;//回溯,取出 i
        }
    }
}

例2:P1036 [NOIP 2002 普及组] 选数 - 洛谷

在n个数中选出k个数,并且不同顺序的算一种;相比例1的全排列问题,我们要去掉重复的数量。

因此最后结果要除以n的全排列也就是n的阶乘。

void dfs(int u)
{
    if (u==k)//当选完k个数后
    {
        int sum=0;
        for (int i=0; i<k; i++)
        {
            sum+=ans[i];
        }
        if (isprimer(sum))
        {
            c++;
            //cout << sum << ' ';
        }
        
        
        
        return ;
    }
    for (int i=0; i<n; i++)
    {
        if (!b[i])//判断这个数有没有被选过。
        {
            ans[u]=a[i];//选入答案数组中
            b[i]=true;
            dfs(u+1);
            b[i]=false;// 恢复现场

        }
    }
    
    
}

例3:P2404 自然数的拆分问题 - 洛谷

题目可以理解为在1到n这些数中可以重复的选一些数,使其和为n。因此dfs在传参时,可加入一个sum参数。

void dfs(int u,int sum)
{
    if (sum>n)//当sum大于n时,不符合条件直接结束该路径(我也是在输出结果看到不对后才想起来的)
    {
        return ;
    }
    if (sum==n)//符合预期
    {
        int ans[15];
        if (cun[0]==n)
        {
            return ;
        }//剪掉不符合要求的答案
        for (int i=0; i<u-1; i++)
        {
            if (cun[i]>cun[i+1])
            {
                return ;
            }//当出现如1 1 1 1 2 1这种重复答案时,直接剪掉,保留1 1 1 1 1 2
            
            //cun.clear();
        }
        for (int i=0; i<u-1; i++)
        {
            cout << cun[i] << '+';
        }//输出最后答案。
        cout << cun[u-1];
        cout << endl;
        return ;
    }
    for (int i=1; i<=n; i++)
    {
        cun[u]=i;
        dfs(u+1,sum+i);//因为可以重复使用数字,所以无bool数组。
        //cun[u]=0;
    }
}

跟例2一样,全排列带来了重复问题

我们只需要判断数组前面的数是否小于后面的数,如果是,就输出。可以有效避免重复问题。

相关文章:

  • 完善机器人:让 DeepSeek 生成 API 接口,并在网页上调用
  • 浅谈数据分析及数据思维
  • Android/AOSP源码编译错误:TEMPORARY_DISABLE_PATH_RESTRICTIONS
  • Linux从零搭建Dify智能体平台(包含网络代理、docker安装、docker镜像地址设置)
  • flinkOracleCdc源码介绍
  • Java8的新特性
  • python如何获取三个小时之前的时间并输出
  • MCP,你的大模型USB通用接口
  • 知网研学赋能研究生教育:提升科研素质与创新能力的实践与探索
  • Vue 3 组件库主题化与可扩展性深度剖析:设计模式与实现策略 - 构建灵活适应多场景的组件库架构
  • 【SpringMVC】常用注解:@RequestParam
  • 大数据面试之路 (二) hive小文件合并优化方法
  • 写一个简单的SQL生成工具
  • 《论语别裁》第01章 学而(25) 善知识与恶知识
  • 数据库MySQL原理(相关程序)
  • Linux第三次作业
  • Unity 笔记:在EditorWindow中绘制 Sorting Layer
  • el-table树形表格合并相同的值
  • 3ds Max 导入到 After Effects 还原摄像机要注意事项--deepseek
  • 【AI 加持下的 Python 编程实战 2_02】第一章:利用 GitHub Copilot 叩开 AI 辅助编程的大门
  • 辽宁援疆前指总指挥王敬华已任新疆塔城地委副书记
  • 美国失去最后的AAA主权评级,继标普、惠誉后再遭穆迪降级
  • 3月中国减持189亿美元美债、持仓规模降至第三,英国升至第二
  • 时隔3年,持续近2小时,俄乌在土耳其谈成了什么?
  • 流失79载,国宝文物“子弹库帛书”(二、三卷)回归祖国
  • 上海虹桥国际咖啡文化节开幕,推出茶咖文化特色街区、宝妈咖啡师培训