dfs搜索

穷举法,又称枚举法,是指从可能的解的集合中一一枚举各个元素,用给定的检验条件判定哪些是无用的,哪些是有用的。能使命题成立即为其解。

穷举法本质上属于搜索算法,但他与搜索有所不同,因为适用于枚举法求解的问题必须满足:可预先确定解的数量;预先确定解变量的取值范围。

穷举算法的关键,首先是确定循环的范围,其次是找出判断解的条件。将这两个关键点解决,穷举算法解题是轻而易举的。

搜索算法和穷举法类似,对于那些无法用循环写出的穷举算法,使用递归或队列来实现求解。搜索的过程构成了一颗搜索树,搜索实际上是对搜索树的遍历。

搜索的顺序分为两种:深度优先搜索(DFS)和广度优先搜索(BFS)。其中深度优先搜索是沿着搜索树的深度遍历树的节点,尽可能深地搜索树的分枝。DFS通常用递归的方法实现。

广度优先搜索每次搜索其可以扩展的每一个节点,当一层节点全部搜索完成后,再依次搜索第一个可扩展节点可以扩展的所有节点。

除了搜索的顺序之外,还有搜索的方法,一般分为盲目搜索和启发式搜索。

启发式搜索是在搜索过程中加入了与问题有关的启发式信息,用于指导搜索朝着最有希望的方向前进,扫除不必要的搜索过程,加速问题求解并得到最优解。

启发式搜索的常见算法有A*算法,模拟退火算法、遗传算法等,我们最常用的是A*算法。A*算法最经典案例是八数码问题,状态函数h设置为未到达目标位置的数字的个数。

递归dfs
n根木棍一共可以拼出多少个不同的三角形

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int n,l[15];
//因为三边总长度是确定的
//将三角形保存为第一边的长度的100倍+第二边的长度
bool h[10000];

//判断三条边是否能构成三角形
//三角形没有出现过,每条边的长度一定比0大,并且两边之和大于第三边
//记录下该三角形
bool is_triangle(int a,int b,int c){
    return !h[a*100+b]&&a&&b&&c&&a+b>c&&a+c>b&&b+c>a&&(h[a*100+b]=true);   
}

//枚举每根木棍放到三堆中的哪一堆中
//再去判断三边
int dfs(int index,int a,int b,int c){
    if(index==n){
        return a<b&&b<c&&is_triangle(a,b,c);
    }
    return dfs(index+1,a+l[index],b,c)+dfs(index+1,a,b+l[index],c)+dfs(index+1,a,b,c+l[index]);
}

int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=0;i<n;++i){
            scanf("%d",&l[i]);
        }
        memset(h,0,sizeof(h));
        printf("%d\n",dfs(0,0,0,0));

    }
    return 0;
}

dfs示例_凑表达式为0

#include <bits/stdc++.h>
using namespace std;
int n; // 保存读入的整数N
bool opr[10]; // 可以用一个bool数组保存所有n-1个符号,我们用true表示加号"+",用false表示减号"-"。
bool found = false; // 表示是否找到一组解,如果没找到的话需要在最后输出"None"
// dfs函数,保存两个状态:deep表示递归深度,就是枚举到第几个数字左边的符号;sum表示之前部分表达式的值。
// 如果枚举完成后sum的值刚好为0,则输出这组方案。我们需要在搜索的过程中用opr数组保存状态。
void dfs(int deep, int sum) {
    // 请在下面的条件表达式中填上对应的值。
    if (deep == n) {
        if (sum == 0) {
            found = true;
            // 请在下面将最终方案输出,方案格式参照题目描述。
            // 最后记得换行哦。
            for(int i=1;i<=n-1;i++){
                if(opr[i])
                    printf("%d+",i);
                else
                    printf("%d-",i);
            }
            printf("%d\n",n);
        }
        return ;
    }
    // 请在下面的语句中填出正确的逻辑。
    opr[deep] = true;
    dfs( deep+1, sum+deep+1);
    opr[deep] = false;
    dfs(  deep+1 , sum-deep-1  );
}

// main函数请自己完成哦,加油~
int main() {
    while(scanf("%d",&n)!=EOF){
        found=false;
        dfs(1,1);
        if(found==false)
            printf("None\n");
    }
    return 0;
}

你可能感兴趣的:(算法,搜索)