题目大意:给定目的状态,给出一个初始状态。问你最少经过多少步能够达到目的状态.
题目思路:
已知起点,终点。可以使用双向广搜来大大减小运行时间.
和普通bfs不同的地方:
1.开始将起点和终点都要加入队列
2.点的标记状态增加至三种0,1,2代表未访问,已从起点访问,已从终点访问.
3.结束条件为:当前访问的点已被另一个状态访问过了。
正确性证明与bfs一致,整体思路与meet in the middle 一致,速度远快于bfs.
stringstream的用法 get
AC代码:
#include<bits/stdc++.h>
using namespace std;
unordered_map<int,int> dist;
unordered_map<int,int> vis;
struct Node{ int s , step , type;};
queue<Node> q;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};
void swap_dig (int & val , int a , int b)
{
stringstream ss;
string tmp = to_string(val);
if (tmp.size() == 8) tmp = '0' + tmp;
swap(tmp[a] , tmp[b]);
ss << tmp;
ss >> val;
}
int main()
{
ios::sync_with_stdio(false);
int a; cin >> a;
int start = 123804765;
if (a == start)
{
cout << 0 << endl;
return 0;
}
dist[a] = 0;
dist[start] = 0;
vis[a] = 1;
vis[start] = 2;
q.push({a , 0 , 1});
q.push({start , 0 , 2});
int ans = 0;
while (q.size()){
Node g = q.front();q.pop();
int pos = 0 , tmp = g.s;
while (tmp % 10){ pos++ , tmp /= 10;}
pos = 8 - pos;
int x = pos / 3, y = pos % 3;
int res = g.s , ggg = res;
bool ok = false;
for (int i = 0 ; i < 4 ; i++){
int nx = x + dx[i];
int ny = y + dy[i];
if (nx < 0 || nx >= 3 || ny < 0 || ny >= 3) continue;
int n_pos = nx * 3 + ny;
swap_dig(res , n_pos , pos);
if (vis.find(res) == vis.end()){
q.push({res , g.step + 1 , g.type});
vis[res] = g.type;
dist[res] = g.step + 1;
}
else if (vis[res] != g.type){
ok = true;
ans = dist[res] + g.step + 1;
break;
}
res = ggg;
}
if (ok) break;
}
cout << ans << endl;
return 0;
}