【搜索】最小步数模型

最小步数模型

问题: 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值