码迷,mamicode.com
首页 > 其他好文 > 详细

dfs(深度优先搜索)

时间:2021-06-02 13:31:26      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:基本   描述   保存   思路   回溯   探索   scan   size   i++   

一、dfs概括:

  搜索与回溯(深度有限搜索)是用于未发现固定计算方式时,通过依次枚举各种情况,来求得最终结果的算法。

二、基本思路:

为了求得问题的解,先选择一种可能情况向前探索,在探索过程中,一旦发现原来的选择是错误的,说明前方已经无路可走,就退回一步重新选择。

这样继续向前探索,知道找到解或者证明无解为止。

 

三、算法框架:

(1)

int search(int k)
{
    for(int i = 1;i <= 当前位置的情况数;i++)
    {
        if(满足条件)
        {
            保存结果
            if(到目的地) 输出解;
            else
            {
                search(k+1);
            }
            恢复保存结果之前的状态(回溯一步);
        }
    }
}

 

(2)

int search(int k)
{
    if(到目的地) 输出解;
    else
    {
        for(int i = 1;i <= 当前位置的情况数;i++)
         {
            if(满足条件)
            {
                保存结果
                search(k+1);
                恢复保存结果之前的状态(回溯一步);
            }
        }
    }
}

 

ps:个人推荐使用第一种模版(至于原因。。。哎呀不要想这么多啦,看着顺眼就行)

四、例题:

(1)全排列问题:(洛谷P1706)

  题目描述

 

     输出自然数 1到 n所有不重复的排列,即 n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

 

  输入格式

 

      一个整数 n

 

  输出格式

 

    由 1 n 组成的所有不重复的数字序列,每行一个序列。

    每个数字保留 5 个场宽

 

 

    基本思路:

  每次确定第i个数字应该放什么(可以放的标准是在当前序列中没有被使用过),确定以后,判断当前所有位置是否已被填满,

  若已经被填满,则直接输出,若没有被填满,则继续向下搜索,判断第i+1位应该放的数字是什么.。

  每输出一次,就把最后一位退掉(jud[i]归0),考虑下一种情况。

  

  这么说到底是有点乱:

  下面用实例模拟解释一下:
  当n==3时

  第一位先取1 进入第二位的选择,因为jud[1] = 1(被用过了),因此选2,再选第三位,因为jud[1] && jud[2] == 1(都被用过了),只能选3,

  因此第一个序列为123

  输出了,回溯一步,发现第三位还是只能选3,因此没有其他情况,再往前回溯一位,进行第二位的选择,此时可以取2、3,2在之前用过,

  因此只能选3,选完后进入第三位的选择,只能选三,选完后发现位数x==3,因此输出,第二个序列为132

  依次类推,得出所有答案。

  

  上代码:
  

#include<cstdio>
using namespace std;
int n, ans[1004] = {}, jud[100004] = {};
void print()//输出函数,每次选满n为后输出当前选出的序列 
{
    for(int i = 1;i <= n;i++)
    {
        printf("    %d", ans[i]);
    }
    printf("\n");
}
void dfs(int x)
{
    for(int i = 1;i <= n;i++)//用于枚举每一位上可能要选的数字(因为这里,所以在前面所有序列不变时,这个位置上不会被重复选择) 
    {
        if(!jud[i])//这个数在之前没有被用过(在当前序列中没有被用过) 
        {
            ans[x] = i;//没用过就可以选入当前序列 
            jud[i] = 1;//这个数被用过了,打上用过的标记 
            if(x == n)//选满了n位,输出 
            {
                print();    
            }
            else dfs(x+1);//如果没选满,就选下一位 
            jud[i] = 0;//所有操作都完成后,回溯一步,去掉i的标记 
        }
    }
}
int main()
{
    scanf("%d", &n);
    dfs(1);
    return 0;    
}

 

 

      

dfs(深度优先搜索)

标签:基本   描述   保存   思路   回溯   探索   scan   size   i++   

原文地址:https://www.cnblogs.com/mint-hexagram/p/14819715.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!