算法基础模板整理(基础搜索篇)
Posted MAKISE004
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法基础模板整理(基础搜索篇)相关的知识,希望对你有一定的参考价值。
递归实现枚举
递归实现指数型枚举
void dfs(int k)
if(k > n)
for(auto &x : res) cout << x << \' \';
cout << endl; return;
dfs(k + 1);
res.push_back(k);
dfs(k + 1);
res.pop_back();
递归实现排列型枚举
void dfs(int k)
if(k > n)
for(int i = 1; i <= n; i ++ ) cout << a[i] << \' \';
cout << endl; return;
for(int i = 1; i <= n; i ++ )
if(st[i]) continue;
st[i] = true;
a[k] = i;
dfs(k + 1);
st[i] = false;
递归实现组合型枚举
void dfs(int k)
int nn = res.size();
if(nn > m || m - nn > n - k + 1) return;
if(k > n)
for(auto &x : res) cout << x << \' \';
cout << endl;
res.push_back(k);
dfs(k + 1);
res.pop_back();
dfs(k + 1);
BFS求最短路
void bfs() // 经典二维数组中 bfs 求最短路
queue<pii> q;
q.push(0, 0);
vis[0][0] = true;
int res = 0;
while(!q.empty())
int nn = q.size();
for(int i = 0; i < nn; i ++ )
auto [x, y] = q.front();
q.pop();
if(x == n - 1 && y == m - 1)
cout << res;
return;
for(int k = 0; k < 4; k ++ )
int nx = x + dx[k], ny = y + dy[k];
if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if(vis[nx][ny] || g[nx][ny]) continue;
q.push(nx, ny);
vis[nx][ny] = true;
res ++ ; //也可开一个dist数组来记录最短路 且可以恰好省去vis数组
int bfs() // 树 or 图 上求点的层次
queue<int> q; q.push(1);
memset(d, -1, sizeof(d));
d[1] = 0;
while(!q.empty())
int u = q.front();
q.pop();
for(int i = h[u]; i != -1; i = ne[i])
int v = e[i];
if(d[v] != -1) continue;
q.push(v), d[v] = d[u] + 1;
return d[n];
DFS判断连通性
bool dfs(int x, int y) //判断两点是否可达
vis[x][y] = true;
if(x == desx && y == desy) return true;
for(int k = 0; k < 4; k ++ )
int nx = x + dx[k], ny = y + dy[k];
if(nx < 0 || nx >= n || ny < 0 || ny >= n) continue;
if(vis[nx][ny] || g[nx][ny] == \'#\') continue;
if(dfs(nx, ny)) return true;
return false;
//----------------------------------------
void dfs(int x, int y) //求连通块个数 也可用bfs
vis[x][y] = true;
for(int k = 0; k < 8; k ++ )
int nx = x + dx[k], ny = y + dy[k];
if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if(vis[nx][ny] || g[nx][ny] == \'#\') continue;
dfs(nx, ny);
for(int i = 0; i < n; i ++ )
for(int j = 0; j < m; j ++ )
if(g[i][j] == \'.\' && !vis[i][j])
dfs(i, j), ans ++ ;
DFS求树的直径
int c; //记录第一次dfs得到的端点
void dfs(int u, int fa)
for(auto &[v, w] : e[u])
if(v != fa)
dist[v] = dist[u] + w;
if(dist[v] > dist[c]) c = v; //记录最远的点
dfs(v, u);
int main()
cin >> n;
for(int i = 1; i < n; i ++ )
int u, v, w; cin >> u >> v >> w;
e[u].push_back(make_pair(v, w));
e[v].push_back(make_pair(u, w));
dfs(1, 0); //找到一个端点c
dist[c] = 0;
dfs(c, 0); //找到c对应的端点
cout << dist[c];
DFS求树的重心
int dfs(int u)
vis[u] = true;
int sum = 1, res = 0;
for(int i = h[u]; i != -1; i = ne[i])
int v = e[i];
if(!vis[v])
int s = dfs(v);
res = max(res, s);
sum += s;
res = max(res, n - sum);//以u为起点向下的最大连通块 向上的连通块 较大者
ans = min(res, ans);
return sum;
回溯
DFS搜索经典案例(Acwing 1116.马走日)
void dfs(int x, int y, int cnt)
if(cnt == n * m) //走满图中所有的点
res ++ ;
return;
for(int k = 0; k < 8; k ++ )
int nx = x + dx[k], ny = y + dy[k];
if(nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if(vis[nx][ny]) continue;
vis[nx][ny] = true;
dfs(nx, ny, cnt + 1);
vis[nx][ny] = false;
DFS剪枝经典案例(Acwing 165.小猫爬山)
void dfs(int k, int cnt)
if(cnt >= res) return; //剪枝
if(k > n)
res = min(res, cnt);
return;
//枚举已有的车是否可存
for(int i = 1; i <= cnt; i ++ )
if(t[i] + a[k] <= W)
t[i] += a[k];
dfs(k + 1, cnt);
t[i] -= a[k];
t[cnt + 1] += a[k];
dfs(k + 1, cnt + 1); //新开一辆车
t[cnt + 1] -= a[k];
状态压缩 递推
经典示例(Acwing 95.费解的开关)
void turn(int x, int y)
for(int k = 0; k < 5; k ++ )
int nx = x + dx[k], ny = y + dy[k];
if(nx < 0 || nx >= 5 || ny < 0 || ny >= 5) continue;
g[nx][ny] ^= 1;
int main()
int t; cin >> t;
while(t -- )
for(int i = 0; i < 5; i ++ ) cin >> g[i];
int ans = 1e7;
for(int k = 0; k < 1 << 5; k ++ )
int step = 0;
memcpy(backup, g, sizeof(g));
//枚举第一行如何操作
for(int i = 0; i < 5; i ++ )
if(k >> i & 1)
step ++ ;
turn(0, i);
//从第一行开始到第四行,依次改变下一行的对应位置的开关
for(int i = 0; i < 4; i ++ )
for(int j = 0; j < 5; j ++ )
if(g[i][j] == \'0\')
step ++ ;
turn(i + 1, j);
//验证最后一行是否都是亮的
bool dark = false;
for(int i = 0; i < 5; i ++ )
if(g[4][i] == \'0\')
dark = true;
break;
if(!dark) ans = min(ans, step);
memcpy(g, backup, sizeof(backup));
if(ans <= 6) cout << ans << endl;
else cout << -1 << endl;
一切都是命运石之门的选择,本文章来源于博客园,作者:Amαdeus,出处:https://www.cnblogs.com/MAKISE004/p/17317078.html,未经允许严禁转载
深度优先搜索算法基础模板
1 void DFS(检索状态) 2 { 3 if(到达目标状态) 4 { 5 ...// 根据题意添加 6 return; 7 } 8 9 if(越界或是不合法状态) return; 10 11 for(扩展方式) 12 { 13 if(扩展方式所达到状态合法) 14 { 15 ....//根据题意来添加 16 标记; 17 DFS(); // 递归调用 18 修改(剪枝); 19 还原标记; 20 //是否还原标记根据题意 21 //如果加上(还原标记)就是 回溯法 22 } 23 } 24 return; 25 }
以上是关于算法基础模板整理(基础搜索篇)的主要内容,如果未能解决你的问题,请参考以下文章