OVSolitario-io

导航

搜索(重复子问题,逻辑相同)&记忆化(缓存数组缓存值)

三种遍历:中先后(顾名思义即看根的顺序)

点击查看代码
void dfs(int u) {
    if(u > n) return ;
    dfs(u + 1);
    cout << u << endl;
    dfs(u + 1);
}

形式是:终止条件 + 逻辑式

STL全排列:

next_permutation()

对于特定顺序开始的全排列:预处理一次顺序

点击查看代码
    if(sum==0){//跑一遍起始顺序
        for(int i = a[k]; i <= n; ++ i){
            if(!vis[i]){
                vis[i] = 1;
                f[k] = i;
                dfs(k + 1);
                vis[i] = 0;
            }
        }
    }
    else{//再往后续跑
        for(int i = 1; i <= n; ++ i){
            if(!vis[i]){
                vis[i] = 1;
                f[k] = i;
                dfs(k + 1);
                vis[i] = 0;
            }
        }
    }

lambda自递归:lambda自递归

取路径:关于取路径

取方案:取方案

对于走迷宫问题的边界判断问题:

截屏2025-10-23 09.56.15

可以人为在边界加一堵墙,来限定迷宫范围

搜索:本质是重复子问题

将规模大的问题转化为形式相同但规模更小的子问题,逻辑相同所以专注于实现本层的逻辑即可

且dfs(pos)含义:1···pos-1层已决定,现考虑第pos位情况

DFS:不断尝试更进一步,碰壁就回头,换一条路继续走
DFS答案会呈现出一颗搜索树的形式

对于回溯: 本质是当前层有x种情况, 当前选择一种, 对剩余x - 1种的考虑

取数:套用枚举子集

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 25;
int n, k, a[N], x[N], ans;
void check(int p) {
    for(int x = 2; x * x <= p; ++ x) {
        if(p % x == 0) {
            return ;
        }
    }
    ++ ans;
}
void dfs(int pos) {
    if(pos == n + 1) {
        int sum = 0, cnt = 0;
        for(int i = 1; i <= n; ++ i) {
            cnt += a[i];
            sum += a[i] * x[i];
        }
        if(cnt != k) return ;
        check(sum);
        return ;
    }
    for(int  i = 0; i <= 1; ++ i) {
        a[pos] = i;
        dfs(pos + 1);
    }
}

int main() {
    cin >> n >> k;
    for(int i = 1; i <= n; ++ i) {
        cin >> x[i];
    }
    dfs(1);
    cout << ans << endl;
    return 0;
}

取数:正解

维护一个数时非必要添加参数,可用以取限制

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int N = 25;
int n, k, a[N], x[N], ans;
void check(int p) {
    for(int x = 2; x * x <= p; ++ x) {
        if(p % x == 0) {
            return ;
        }
    }
    ++ ans;
}
void dfs(int pos) {
    if(pos == k + 1) {
        int sum = 0;
        for(int i = 1; i <= k; ++ i) {
            sum += x[a[i]];
        }
        check(sum);
        return ;
    }
    for(int  i = a[pos - 1] + 1; i <= n; ++ i) {//保证第pos位+1严格递增
        a[pos] = i;
        dfs(pos + 1);
    }
}

int main() {
    cin >> n >> k;
    for(int i = 1; i <= n; ++ i) {
        cin >> x[i];
    }
    dfs(1);
    cout << ans << endl;
    return 0;
}

BFS(顺序结构,有序性):逐层扩展 BFS

BFS逐层扩展,所以当BFS搜索树为去掉非最短路径情况时会出现一棵最短路径树

队列(First In First Out):先存一步能到的点,然后再存两步能到的点,再生成3步能到····,保证了离起点更近一定有先入队

BFS其中的队列优化,但其实本质是不用队列而是形式上处于类似分裂思想
例如:

点击查看代码
如迷宫问题:
每次可以分裂为4个情况走到下一个点,且有先分裂一定有比后分裂离起点更近,后分裂一定比起点更远

因BFS逐层扩展,所以当初次访问在k层,意味着走k步可以到达这个点

BFS框架:

1.建队
2.(非空时)将本层能拓展到的all点加入队列,并弹出本层

剪枝

记忆化搜索

使程序更简洁

DFS的两种状态表示形式:
全局变量存储:

int sum = 0;
void dfs(int u) {
    if(找到答案) {
        输出或统计 sum;
        return;
    }
    for(枚举下一步操作) {
        if(合法操作) {
            sum = sum + a[i];
            dfs(u + 1);
            sum = sum - a[i];//此时需要对sum回溯
        }
    }
}

函数参数存储传递:

void dfs(int u, int sum) {
    if(找到答案) {
        输出或统计 sum;
        return;
    }
    for(枚举下一步操作) {
        if(合法操作) {
            dfs(u + 1, sum + a[i]);//无须回溯
        }
    }
}

构造函数: 无赋值时为构造的默认值

STL容器中基本都包含构造函数,用来初始化STL

构造函数:

struct AK {
    int x, y;
    AK(int sx = 0, int sy = 0) {//构造函数与结构体同名,无须返回值
        x = sx, y = sy;
    }
}

调用:2种

AK tmp(1, 1);//在新创建的tmp中赋值即tmp.x和tmp.y
q.push(tmp);
//临时变量
q.push(AK(1, 1));

posted on 2025-07-25 14:17  TBeauty  阅读(245)  评论(0)    收藏  举报