搜索(重复子问题,逻辑相同)&记忆化(缓存数组缓存值)
三种遍历:中先后(顾名思义即看根的顺序)
点击查看代码
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自递归
取路径:关于取路径
取方案:取方案
对于走迷宫问题的边界判断问题:

可以人为在边界加一堵墙,来限定迷宫范围
搜索:本质是重复子问题
将规模大的问题转化为形式相同但规模更小的子问题,逻辑相同所以专注于实现本层的逻辑即可
且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));
浙公网安备 33010602011771号