前置知识:BFS(宽度优先搜索)_如何何何的博客-CSDN博客
给定一个初始集合与一些操作,可以对该集合执行给定的操作,要求将集合变换成目标集合,求最少的操作次数。
将集合的每种状态看做点,每种操作看做一条边,即可将此类问题抽象为求解两点间的最短路径,且每条边的权值都为 1 ,可用宽度优先搜索解决。
例题1.八数码
将网格看做点,对起点进行宽度优先搜索查找终点即可;
网格可用 string 存储;
由于网格只有九个点,交换操作数量较少,可用记录所有操作,搜索时枚举所有情况即可。
AC代码如下:
#include<iostream>
#include<cstring>
#include<unordered_map>
#include<queue>
#include<vector>
using namespace std;
const int N=10;
unordered_map<string,int>d;//每个状态的步数
vector<int>v[N];
string E=" 12345678x";
int bfs(string S){
if(S==E)return 0;
queue<string>q;
q.push(S);
d[S]=0;
while(q.size()){
string t=q.front();//取队头
q.pop();//删队头
//查找x的位置
int x=-1;
for(int i=1;i<=9;i++)
if(t[i]=='x')x=i;
//操作当前状态
for(int i=0;i<v[x].size();i++){
string k=t;
char c=k[x];k[x]=k[v[x][i]];k[v[x][i]]=c;//交换操作
if(k==E)return d[t]+1;//如果达到目标状态
//如果该状态还没搜到
if(!d.count(k)){
d[k]=d[t]+1;
q.push(k);
}
}
}
return -1;
}
int main(){
//打表每个点的交换位置
v[1].push_back(2),v[1].push_back(4);
v[2].push_back(1),v[2].push_back(3),v[2].push_back(5);
v[3].push_back(2),v[3].push_back(6);
v[4].push_back(1),v[4].push_back(5),v[4].push_back(7);
v[5].push_back(2),v[5].push_back(4),v[5].push_back(6),v[5].push_back(8);
v[6].push_back(3),v[6].push_back(5),v[6].push_back(9);
v[7].push_back(4),v[7].push_back(8);
v[8].push_back(5),v[8].push_back(7),v[8].push_back(9);
v[9].push_back(6),v[9].push_back(8);
//输入初始状态
string S=" ";//下标从1开始i
for(int i=0;i<9;i++){
char c;
cin>>c;
S+=c;
}
cout<<bfs(S);
return 0;
}
例题2:抓住那头牛
AC代码如下:
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
const int N = 1e5 + 10;
int s, e;
int t[N];//到每个点用的时间
bool st[2 * N];
int l, r;//给定两个大致范围防止爆栈
int bfs() {
if (s == e)return 0;
queue<int>q;
q.push(s);
st[s] = true;
while (q.size()) {
int tmp = q.front();
q.pop();
int a = tmp + 1, b = tmp - 1, c = tmp * 2;
if (a > l && a < r && !st[a]) { st[a] = true; t[a] = t[tmp] + 1; q.push(a); if (a == e)return t[a]; }
if (b > l && b < r && !st[b]) { st[b] = true; t[b] = t[tmp] + 1; q.push(b); if (b == e)return t[b]; }
if (c > l && c < r && !st[c]) { st[c] = true; t[c] = t[tmp] + 1; q.push(c); if (c == e)return t[c]; }
}
return -1;
}
int main() {
cin >> s >> e;
l = -1, r = N;
cout << bfs();
return 0;
}