题目
题解
BFS。
先讲标准做法,对应代码2:
用map
类型的vis
记录某个状态是否经历过;什么是状态,状态就是比如12345678.
或123.46758
,这些string
型的数值就对应着一个个状态,即网格中数字和空格的不同排法。
pair 知识点:
队列中结点的类型为pair<string, int>
,pair<string, int>
相当于一个结构体里面有两个元素,一个是string
类型,另一个是int
类型,分别记录状态和到达此状态的步数。pair
的第一个元素通过.first
访问,第二个元素通过.second
访问。
习惯上,我们一般直接将pair<int, int>
typedef
成PII
,类似地,我将pair<string, int>
typedef
成PSI
。另外还习惯上将first
define
成x
,second
define
成y
,但是我不习惯。
每次扩展儿子结点都是让空格去上下左右移动,让空格与满足条件的位置上的数交换,插入队列,不断循环直至到达目标状态或无可扩展结点,输出结果。
这个耗时比较卡点,再多点奇奇怪怪的操作就TLE了。
再将最为重要的双向广搜,因为我也是第一次用,所以好好讲讲(虽然没什么好讲的)
对应代码1。
正如它的名字一样,从初始状态和目标状态同时进行BFS,当其中一个搜索搜索到了一个两个搜索都搜索过的状态了,那么从初始状态到目标状态的最小步数就是第一个搜索记录的步数与第二个搜索记录的步数之和。
道理也很简单,不予证明。
会写广搜的,随便扫一眼就会了。
提几点注意:
- 这里的
map
类型要保存的是到达某状态的步数,而不仅仅是是否到达过了。 - 结束条件是同一个字符串在两个
map
中都存在。
最后一个代码3,随便看看就得了,图一乐,我的垃圾做法。
代码1:双向广搜
// 双向广搜 53s
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<string, int> PSI;
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
int ans = -1;
queue<PSI> Q1, Q2;
string ss, tt;
map<string, int> step1, step2;
int main()
{
cin>>ss>>tt;
Q1.push(PSI(ss, 0));
Q2.push(PSI(tt, 0));
step1[ss] = 0;
step2[tt] = 0;
while(!Q1.empty() && !Q2.empty()) {
if(!Q1.empty()) {
PSI p = Q1.front();
Q1.pop();
string pstr = p.first;
int pstep = p.second;
int idx = pstr.find('.');
for(int i = 0;i < 4;i ++) {
int tx = idx/3 + dx[i], ty = idx%3 + dy[i];
int nxt = tx*3+ty;
if(tx < 0 || tx >= 3 || ty < 0 || ty >= 3 || nxt == idx) continue;
string tmpstr = pstr;
swap(tmpstr[idx], tmpstr[nxt]);
if(step1[tmpstr]) continue;
step1[tmpstr] = pstep+1;
if(step2[tmpstr]) {cout<<step1[tmpstr]+step2[tmpstr]; return 0;}
Q1.push(PSI(tmpstr, pstep + 1));
}
}
if(!Q2.empty()) {
PSI p = Q2.front();
Q2.pop();
string pstr = p.first;
int pstep = p.second;
int idx = pstr.find('.');
for(int i = 0;i < 4;i ++) {
int tx = idx/3 + dx[i], ty = idx%3 + dy[i];
int nxt = tx*3+ty;
if(tx < 0 || tx >= 3 || ty < 0 || ty >= 3 || nxt == idx) continue;
string tmpstr = pstr;
swap(tmpstr[idx], tmpstr[nxt]);
if(step2[tmpstr]) continue;
step2[tmpstr] = pstep+1;
if(step1[tmpstr]) {cout<<step1[tmpstr]+step2[tmpstr]; return 0;}
Q2.push(PSI(tmpstr, pstep + 1));
}
}
}
cout<<ans<<endl;
return 0;
}
代码2:标准做法
// 992s
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<string, int> PSI;
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
int ans = -1;
queue<PSI> q;
string ss, tt;
map<string, int> vis;
int main()
{
cin>>ss>>tt;
q.push(PSI(ss, 0));
vis[ss] = 1;
while(!q.empty()) {
PSI p = q.front();
q.pop();
string pstr = p.first;
int pstep = p.second;
int idx = pstr.find('.');
if(tt == pstr) {ans = pstep; break;}
for(int i = 0;i < 4;i ++) {
int tx = idx/3 + dx[i], ty = idx%3 + dy[i];
int nxt = tx*3+ty;
if(tx < 0 || tx >= 3 || ty < 0 || ty >= 3 || nxt == idx) continue;
string tmpstr = pstr;
swap(tmpstr[idx], tmpstr[nxt]);
if(vis[tmpstr] == 1) continue;
vis[tmpstr] = 1;
q.push(PSI(tmpstr, pstep + 1));
}
}
cout<<ans<<endl;
return 0;
}
代码3
// 878s
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
int pos, step;
ll idx;
node() {}
node(int p, int s, ll i) {pos = p; step = s; idx = i;}
};
queue<node> q;
int ans = -1, pos;
ll start, des;
string ss, tt;
map<int, int> vis;
int dx[4] = {-1, 1, 0, 0};
int dy[4] = {0, 0, -1, 1};
int main()
{
cin>>ss>>tt;
for(int i = 0;i < 9;i ++) {
if(ss[i]=='.') pos = i, start = start*10 + 9;
else start = start*10 + (ss[i]-'0');
des = des*10 + (tt[i]=='.'?9:(tt[i]-'0'));
}
q.push(node(pos, 0, start));
while(!q.empty()) {
node t = q.front();
q.pop();
int tpos = t.pos;
ll tidx = t.idx;
if(des == t.idx) {ans = t.step; break;}
for(int i = 0;i < 4;i ++) {
int tx = (t.pos)/3 + dx[i], ty = (t.pos)%3 + dy[i];
int nxt = tx*3+ty;
if(tx < 0 || tx >= 3 || ty < 0 || ty >= 3 || nxt == t.pos) continue;
ll x = pow(10, 8-nxt), y = pow(10, 8-tpos);
ll high1 = tidx/x, low1 = tidx%x;
ll num = high1%10;
ll tmp = (high1/10*10 + 9) * x + low1;
ll high2 = tmp/y, low2 = tmp%y;
tmp = (high2/10*10 + num) * y + low2;
// cout<<nxt<<' '<<tidx<<' '<<high1<<' '<<low1<<' '<<num<<' '<<high2<<' '<<low2<<' '<<tmp<<endl;
if(vis[tmp] == 1) continue;
vis[tmp] = 1;
q.push(node(nxt, t.step+1, tmp));
}
}
cout<<ans<<endl;
return 0;
}