zoukankan      html  css  js  c++  java
  • 剪枝

    DFS(深度优先搜索)是一种常见的算法,大部分的题目都可以用 DFS 解决,

    但是大部分情况下,这都是骗分算法,很少会有爆搜为正解的题目。

    因为 DFS 的时间复杂度特别高。(没学过 DFS 的请自行补上这一课)

    既然不能成为正解,那就多骗一点分吧。

    那么这一篇文章将介绍一些实用的优化算法(俗称“剪枝”)。

    题目:求9个数字以内的全排列 (我们以三个数字的为例子)

    正常猛男大力搜索代码(

    #include<bits/stdc++.h>

    using namespace std;

    int a[3];

    int dfs(int n){

    if(n==3){

    for(int i=0;i<3;i++)

    printf("%d",a[i]);

    return 0*printf(" "); //看不懂的考虑下函数返回值的问题

    }

    for(int i=0;i<3;i++){

    a[n]=i; dfs(n+1); //不能用n++或者++n;

    }

    }

    int main(){

    int t=dfs(0);

    }

    得到的结果 000 001 002 010 011 012 020 021 022 100 101 102。。。

    我们想要的结果 012 021 102 120 201 210

    如何只把我们需要的答案输出出来?

    我们经常用的剪枝有:可行性剪枝、最优性剪枝、记忆化搜索、搜索顺序剪枝。

    其中可行性剪枝就是把能够想到的不可能出现的情况给它剪掉 。

    该方法判断继续搜索能否得出答案,如果不能直接回溯。

    比如a[0]=0时,a[1]便不能为0了

    #include<bits/stdc++.h>

    using namespace std;

    int a[3],b[3];

    int dfs(int n){

    if(n==3){ for(int i=0;i<3;i++)

    printf("%d",a[i]);

    return 0*printf(" "); //看不懂的考虑下函数返回值的问题

    } for(int i=0;i<3;i++){

    if(b[i]){ b[i]=0; a[n]=i; dfs(n+1); //不能用n++或者++n;

    b[i]=1;

    }

    }

    }

    int main(){

    for(int i=0;i<3;i++)

    b[i]=1;

    int t=dfs(0);

    }

    如果我们想打表:

    #include<bits/stdc++.h>

    using namespace std;

    int qqq=4,num=0;

    int a[10],b[10];

    int dfs(int n){

    if(n==qqq){

    num++;

    return 0;

    }

    for(int i=0;i<qqq;i++){

    if(b[i]){

    b[i]=0;

    a[n]=i;

    dfs(n+1); b[i]=1;

    }

    }

    }

    int main(){

    for(qqq=1;qqq<5;qqq++){

    num=0;

    for(int i=0;i<qqq;i++)

    b[i]=1;

    int t=dfs(0);

    printf("%d ",num);

    }

    }

    得到:1 2 6 24

    进入http://oeis.org

    我们发现还有很多公式,

    那我们把1-9都打出来 1 2 6 24 120 720 5040 40320 362880

    进入http://oeis.org,我们发现少了一些。

    由此,我们发现 A000142就是我们要的

    即n个数字全排列,总方案数为N!

    如果题目要我们求n个数字全排列的总方案数,我们不必再搜索一遍,直接输出N!即可

    欢迎来我们oj刷题 oj地址:http://www.npumdacm.top/
  • 相关阅读:
    种子爆破&[GWCTF 2019]枯燥的抽奖
    Springboot学习笔记(三)
    Springboot学习笔记(二)
    Springboot学习笔记(一)
    深入理解java虚拟机阅读笔记(二)对象是否存活与垃圾收集算法
    深入理解java虚拟机阅读笔记(一)java内存区域
    OOP和AOP的区别
    浅谈对spring的理解
    mybatis逆向工程配置文件
    mybatis中${}和#{}的区别
  • 原文地址:https://www.cnblogs.com/tlysMoodspace/p/11813815.html
Copyright © 2011-2022 走看看