BFS
题型:出现起点,出现终点
用法:一层一层搜索,每一层与起点的距离等长
如:
先 1 入队
1 出队
1的连接点 2,3,4入队
2,3,4依次出队
2,3,4的连接点5,9,7,8,6依次入队
…
以此类推
每次入队和出队的都是一层一层的
1、走迷宫
https://www.acwing.com/problem/content/846/
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[101][101];
int k[101][101];
struct node{
int x,y;
}p;
queue<node> q;
//x上至下 y左至右
//上 下 左 右
int dir[4][2]={
1,0,-1,0,0,-1,0,1};
int bfs(){
int res = 0;
//第一个点入队
q.push({
0,0});
//当队列有元素存在
while(!q.empty()){
p=q.front();//取出q的顶点元素
q.pop();//释放
int dx ,dy;
for(int i=0;i<4;++i){
dx=p.x+dir[i][0],dy=p.y+dir[i][1];
if(dx<0||dy>=m||dx>=n||dy<0||k[dx][dy]||a[dx][dy]==1){
//越界||为墙||走过
continue;
}
//在上一层的基础上 + 1 (离起点的距离加1)
k[dx][dy]=k[p.x][p.y]+1;
//入队
q.push({
dx,dy});
}
}
return k[n-1][m-1];
}
int main(){
cin>>n>>m;
for(int i=0;i<n;++i)
for(int j=0;j<m;++j)
cin>>a[i][j];
cout<<bfs();
return 0;
}
2、八数码
https://www.acwing.com/problem/content/847/
注意点:
<1 记录出现过的状态—可使用变进制数
<2 一维数组与二维数组的相互转化
#include<iostream>
#include<queue>
#include<algorithm>
#include<string>
using namespace std;
const int N = 4*1e5 + 10;
bool vis[N];
string start;
int fact[9]={
1};
struct point{
int step;//记录步数
string s;
};
int dx[4]={
1,0,-1,0},dy[4]={
0,1,0,-1};
//变进制数--逢i进1
//根据逆序对个数
int hash_map(string s){
int res = 0;
for(int i=0;i<9;++i){
int k =0;
for(int j=0;j<i;++j){
if(s[j]>s[i]) k++;
}
res+=k*fact[i];
}
return res;
}
int bfs(){
vis[hash_map(start)]=true;
point p;
p.s = start;
p.step = 0;
string end = "12345678x";
queue<point>q;
q.push(p);
while(!q.empty()){
p = q.front();
q.pop();
int distance = p.step;
if(p.s==end) return distance;
//x位置
int k = (p.s).find('x');
//一维化二维
int x = k/3;
int y = k%3;
for(int i=0;i<4;++i){
int nx = x+dx[i],ny = y+dy[i];
if(nx<0||nx>=3||ny<0||ny>=3) continue;
//二维化一维
swap(p.s[k],p.s[nx*3+ny]);
int h = hash_map(p.s);
if(!vis[h]){
vis[h]=true;
p.step=distance +1;
q.push(p);
}
swap(p.s[k],p.s[nx*3+ny]);
}
}
return -1;
}
int main(){
//初始化变进制数
//i!初始化
for(int i=1;i<9;++i) fact[i]=fact[i-1]*i;
fact[0]=0;
char c;
for(int i=0;i<9;++i){
cin>>c;
start+=c;
}
cout<<bfs();
return 0;
}