最小步数模型
问题: BFS的最小步数模型就是给我们一个整体,我们可以对这个整体进行一些操作,问我们最小要几步可以得到我们要的状态。
有三个点要思考: 1. 如何记录状态 2. 如何记录步数 3.如何标记
- 记录状态可以用int,string之类的,放到队列中
- 记录步数可以用
map
记录,标记的话当mp.count() == 0
时代表未访问过。
八数码
AC代码(19MB):
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
string st, ed = "12345678x";
unordered_map<string, int>dis;
vector<int>ne[9] = {{1, 3}, {0, 2, 4}, {1, 5}, {0, 4, 6}, {1, 3, 5, 7}, {2, 4, 8}, {3, 7}, {4, 6, 8}, {5, 7}};
int bfs()
{
if(st == ed) return 0;
queue<string>que;
que.push(st);
dis[st] = 0;
while(!que.empty())
{
string t = que.front();
int now_dis = dis[t];
que.pop();
int idx = t.find('x');
for(auto xx : ne[idx]){
swap(t[idx], t[xx]);
if(t == ed) return now_dis + 1;
if(dis.count(t)) { swap(t[idx], t[xx]); continue; }
dis[t] = now_dis + 1;
que.push(t);
swap(t[idx], t[xx]);
}
}
return -1;
}
int main()
{
char ch;
for(int i=0; i<9; i++){
scanf(" %c", &ch);
st += ch;
}
printf("%d", bfs());
system("pause");
return 0;
}
八数码【加强版】
单源bfs的TLE代码:
http://acm.hdu.edu.cn/viewcode.php?rid=37066416
【2021牛客多校】Penguins
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 21;
typedef pair<int, int> PII;
#define fi first
#define se second
char s1[N][N], s2[N][N];
int dis[N][N][N][N];
pair<PII, PII> fa[N][N][N][N];
char faa[N][N][N][N];
int dx[] = {0, 0, 1, -1};
int dy1[] = {1, -1, 0, 0}, dy2[] = {-1, 1, 0, 0};
void bfs()
{
memset(dis, -1, sizeof dis);
for(int i=0; i<20; i++)
for(int j=0; j<20; j++)
for(int k=0; k<20; k++)
for(int l=0; l<20; l++)
fa[i][j][k][l].fi = fa[i][j][k][l].se = make_pair(-1, -1);
queue<pair<PII, PII> > que;
que.push({{19, 19}, {19, 0}});
dis[19][19][19][0] = 0;
while(!que.empty())
{
auto tp = que.front(); que.pop();
int x1 = tp.fi.fi, y1 = tp.fi.se, x2 = tp.se.fi, y2 = tp.se.se;
for(int i=0; i<4; i++)
{
int xx1 = x1 + dx[i], yy1 = y1 + dy1[i];
int xx2 = x2 + dx[i], yy2 = y2 + dy2[i];
if(xx1 < 0 || xx1 >= 20 || yy1 < 0 || yy1 >= 20 || s1[xx1][yy1] == '#') xx1 -= dx[i], yy1 -= dy1[i];
if(xx2 < 0 || xx2 >= 20 || yy2 < 0 || yy2 >= 20 || s2[xx2][yy2] == '#') xx2 -= dx[i], yy2 -= dy2[i];
if(dis[xx1][yy1][xx2][yy2] != -1) continue;
faa[xx1][yy1][xx2][yy2] = "RLDU"[i];
dis[xx1][yy1][xx2][yy2] = dis[x1][y1][x2][y2] + 1;
fa[xx1][yy1][xx2][yy2] = tp;
que.push({{xx1, yy1}, {xx2, yy2}});
}
}
cout << dis[0][19][0][0] << endl;
string ans;
pair<PII, PII> now = {{0, 19}, {0, 0}};
while(now.fi.fi != -1 && now.fi.se != -1 && now.se.fi != -1 && now.se.se != -1)
{
pair<PII, PII> nxt = fa[now.fi.fi][now.fi.se][now.se.fi][now.se.se];
ans += faa[now.fi.fi][now.fi.se][now.se.fi][now.se.se];
s1[now.fi.fi][now.fi.se] = 'A';
s2[now.se.fi][now.se.se] = 'A';
now = nxt;
}
reverse(ans.begin(), ans.end());
ans = ans.substr(1);
cout << ans << endl;
for(int i=0; i<20; i++) cout << s1[i] << " " << s2[i] << endl;
}
int main()
{
for(int i=0; i<20; i++) cin >> s1[i] >> s2[i];
bfs();
system("pause");
return 0;
}