目录
1.概念
2.DFS->八皇后
3.BFS->奇怪的电梯
1.概念
深度优先搜索(DFS),一条路走到黑,回溯,遍历所有节点
广度优先搜索(BFS),层层递进,遍历所有节点
深搜和广搜可以提高枚举的效率,是我们解决问题的重要工具
2.DFS->八皇后
问题描述:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行、同一列或同一斜线上,问有多少种摆法。著名数学家高斯认为有76种方案。1854年在柏林的象棋杂志上不同的作者发表了40种不同的解,后来有人用图论的方法解出92种结果。今天,我们可以用计算机来AC这个高斯回答错误的问题。
我们可以进行一下模拟,例如现在将前三行棋子的位置输出,并输出最终结果数。可以定义一个二维数组表示棋盘,不过显然那样会增加时间复杂度,不妨直接开一个一维数组a[i]=j表示第i行皇后放在第j列上,用三个b数组判断皇后是否可以放置,然后就可以利用DFS来解决这道题目了。
代码:
#includeusing namespace std; //DFS算法 八皇后 #define maxn 100 int a[maxn], n, ans = 0; int b1[maxn], b2[maxn], b3[maxn]; //b1记录第i列,b2记录x+y=i斜列,b3记录x-y+15=i斜列 ->是否可放 void dfs(int x)//第x行皇后放哪 { if (x > n) { ans++; if (ans <= 3)//输出了前三种,也可以输出所有种情况 { for (int i = 1; i <= n; i++) cout << a[i] << " "; cout << endl; } return; } for(int i=1;i<=n;i++) if (b1[i] == 0 && b2[x + i] == 0 && b3[x - i + 15] == 0)//可放置 { a[x] = i;//第x行皇后放在第i列上 b1[i] = 1; b2[x + i] = 1; b3[x - i + 15] = 1; dfs(x + 1);//递归下一行 b1[i] = 0; b2[x + i] = 0; b3[x - i + 15] = 0;//回溯 } } int main() { cin >> n; dfs(1); cout << ans; return 0; }
也可以将所有可能的情况打表输出:
#include//这段代码时间复杂度有点高qwq using namespace std; int f[16][16],cnt=0; int n; void print() { for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) cout << f[i][j] << " "; cout << endl; } cout << endl; } bool check(int x,int y) { for (int i = 1; i <= n; i++) if (f[i][y] == 1) return false; for(int i=1;i<=n;i++) for (int j = 1; j <= n; j++) { if (f[i][j] == 1 && (x - y == i - j || x + y == i + j)) return false; } return true; } void dfs(int row) { if (row == n + 1) { cnt++; print(); return; } for(int j=1;j<=n;j++) if (check(row,j)) { f[row][j] = 1; dfs(row + 1); f[row][j] = 0; } } int main() { cin >> n; dfs(1); cout << cnt< 3.BFS->奇怪的电梯
问题描述:有一天桐桐做了一个梦,梦见了一种很奇怪的电梯。大楼的每一层楼都可以停电梯,而且第i层楼(1≤i≤N)上有一个数字K;(0≤Ki≤N)。电梯只有四个按钮:开,关,上,下。上下的层数等于当前楼层上的那个数字。当然,如果不能满足要求,相应的按钮就会失灵。例如:3 3 1 2 5代表了Ki (K1=3,K2=3,…),从一楼开始。在一楼,按“上,”可以到4楼,按“下”是不起作用的,因为没有-2楼。那么,从A楼到B楼至少要按几次按钮呢?
对于BFS,我们可以借助先进先出的队列来完成。
代码:
#include#include //BFS算法 奇怪的电梯 using namespace std; bool visited[205];//记录是否已经到过这层,最短路径问题,到走过的楼层无意义 struct node//楼层节点 { int now;//当前层数 int count;//当前启用电梯次数 }; queue Q;//用来保存当前楼层节点,先进先出 int kk[205];//第i层上的number int main() { int n, a, b; cin >> n >> a >> b; for (int i = 1; i <=n; i++) cin >> kk[i]; Q.push(node{ a, 0 });//入队 while (not Q.empty()) { node u = Q.front();//提取队首元素 Q.pop();//弹出队首元素 if (u.now == b)//是目标楼层,结束 { cout << u.count; return 0; } int df = u.now + kk[u.now];//上楼 if (df <= n && not visited[df])//是否能走 { visited[df] = true; Q.push(node{ df,u.count + 1 }); } df = u.now - kk[u.now];//下楼 if (df >= 1 && not visited[df])//是否能走 { visited[df] = true; Q.push(node{ df,u.count + 1 }); } } cout << "-1"; return 0; }



