1.1 DFS模板(深度优先遍历)
- 模板
c++
全局状态变量
void dfs(当前状态)
{
if(当前状态是目标状态) // 判断
进行相应处理(输出当前解、更新最优解、退出返回等)
// 扩展
for(所有可行的新状态)
{
if(新状态没有访问过 && 需要访问) // 可行性剪枝、最优性剪枝、重复性剪枝
{
标记
dfs(新状态);
取消标记
}
}
}
int main()
{
...
dfs(初始状态);
...
}
-
例题:
题目描述
输出自然数 1∼n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复数字。
输入格式
一行,一个整数 n。
输出格式
输出由 1∼n 组成的所有不重复的数字序列。每行一个序列,行内数字之间用空格隔开。
样例
输入:
3
输出:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
数据范围
对于 100% 的测试数据满足:1≤n≤9。
代码:
c++
#include<bits/stdc++.h>
using namespace std;
int n,a[10];
bool f[10];
void prin(){
for(int i=1;i<=n;i++){
cout<<a[i]<<" ";
}
cout<<endl;
}
void dfs(int k){
for(int i=1;i<=n;i++){
if(f[i]==false){
a[k]=i;
f[i]=true;
if(k==n) prin();
else dfs(k+1);
f[i]=false;
}
}
}
int main(){
cin>>n;
dfs(1);
return 0;
}
1.2 BFS模板(广度优先遍历)
-
模板
c++全局状态变量 void BFS() { 定义状态队列 初始状态入队 while(队列不为空) { 取出队首状态作为当前状态 if(当前状态是目标状态) 进行相应处理(输出当前解、更新最优解、退出返回等) else for(所有可行的新状态) { if(新状态没有访问过 && 需要访问) { 新状态入队 } } } }
-
例题:
题目描述
有一天我做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第 i层楼(1≤ i*≤* N*)上有一个数字 Ki (0≤Ki ≤N )。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:从一楼开始,3 3 1 2 5代表了Ki (K 1=3,K2=3,......) 。在一楼,按"上"可以上 3 层到 4 楼,按"下"是不起作用的,因为没有 -2 楼。那么,从 A 楼到 B 楼至少要按几次按钮呢?
输入格式
输入共有二行,第一行为三个用空格隔开的正整数,表示N*,A ,B ,第二行为 N 个用空格隔开的正整数,表示Ki*。
输出格式
输出仅一行,即最少按键次数,若无法到达,则输出 -1。
样例输入与输出
输入数据
input15 1 5 3 3 1 2 5
输出数据
output13
样例解释
输入解释
第一行的数据 5表示总共5层楼,第二个数据1表示初始在1楼,第三个数据5表示我们最终的目的地是5楼。
第二行的数据 第二行输入了5个数,分别表示每一层的电梯能上下几层。
第一个数3 表示在1楼可以上3层楼,到达4楼;也可以下3层楼,但是我们没有-2层楼,所以从1楼下3层不行。
第二个数3 表示在2楼可以上3层楼,到达5楼;也可以下3层楼,但是我们没有-1层楼,所以从2楼下3层不行。
第三个数1 表示在3楼可以上1层楼,到达4楼;也可以下1层楼,到达2楼。输出解释
那么我们初始在1楼,只能上3层到达4楼,在4楼只能下2层到达2楼,然后上3层到达5楼。总共用了3步,所以最终输出3。
数据范围
对于 100% 的测试数据满足:1≤N ≤200,1≤A ,B ≤N。
-
代码:
c++#include <bits/stdc++.h> using namespace std; int n, a, b; // 输入的数值范围n,起点a,终点b int x[205], step[205]; // 数组x用于存储每个位置可以跳跃的步数,step数组用于标记每个位置的步数 queue<int> q; // 队列用于广度优先搜索 // 广度优先搜索函数 void bfs() { q.push(a); // 将起点a加入队列 step[a] = 0; // 将起点的步数标记为0 while (!q.empty()) { // 当队列不为空时循环 int t = q.front(); // 取出队首元素 q.pop(); // 弹出队首元素 if (t == b) { // 如果当前位置等于终点b cout << step[b]; // 输出步数 return ; // 结束搜索 } if (t - x[t] >= 1 && !step[t - x[t]]) { // 如果向下跳不越界且下一个位置未被访问过 q.push(t - x[t]); // 将下一个位置加入队列 step[t - x[t]] = step[t] + 1; // 更新下一个位置的步数 } if (t + x[t] <= n && !step[t + x[t]]) { // 如果向上跳不越界且下一个位置未被访问过 q.push(t + x[t]); // 将下一个位置加入队列 step[t + x[t]] = step[t] + 1; // 更新下一个位置的步数 } } cout << -1; // 如果无法到达终点b,输出-1 } int main() { cin >> n >> a >> b; // 输入数值范围n,起点a,终点b for (int i = 1; i <= n; i++) // 输入每个位置的可跳跃步数 cin >> x[i]; bfs(); // 进行广度优先搜索 }