三、多源bfs && 四、最小步数模型

三、多源bfs

173. 矩阵距离 - AcWing题库

题意:找出所有点的最短曼哈顿距离

思路:对于多源bfs来说,如果有多个相同起点的,我可以直接将所有相同起点加入到队列。从而因为层序遍历会每次把所有为1的点都遍历一遍(涉及到每一层)

    #include<bits/stdc++.h>

using namespace std;

#define ll long long
#define PII pair<int, int>
#define PLL pair<ll, ll>

const int N = 1010;
const int M = 2 * N;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps = 1e-8;

int n,m;
char mp[N][N];
int dist[N][N];
bool st[N][N];
int hr[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
void bfs()
{
    memset(dist,INF,sizeof dist);
    queue<PII>q;
    for(int i = 0 ; i < n; i ++)
        for(int j = 0;j < m; j ++)
        {
            if(mp[i][j] == '1')
            {
                q.push({i,j});
                dist[i][j] = 0;
                st[i][j] = 0;
            }
        }
    while(q.size())
    {
        auto t = q.front();
        q.pop();
        for(int i = 0; i < 4; i ++)
        {
            int a = t.first + hr[i][0];
            int b = t.second + hr[i][1];
            if(a < 0 || a >= n || b < 0 || b >= m) continue;
            if(st[a][b]) continue;//第一次已经搜到的点一定已经是最小,类dij
            if(dist[a][b] > dist[t.first][t.second] + abs(t.first - a) + abs(t.second - b))
            {
                dist[a][b] = dist[t.first][t.second] + abs(t.first - a) + abs(t.second - b);
                q.push({a,b});
                st[a][b] = 1;
            }
        }
    }
    

}
void solve()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++) cin >> mp[i];

    bfs();
    for(int i = 0; i < n; i ++)
    {
        for(int j = 0; j < m; j ++)
        {
            if(j) cout << " ";
            cout << dist[i][j];
        }
        cout << endl;
    }
        

}
int main()
{
    solve();



    system("pause");
    return 0;
}

四、最小步数模型

845. 八数码 - AcWing题库

题意:找到可变换的最小步数

思路:

1、对于string类的bfs搜索可以用unordered_map存距离

2、同时n * n的展开可用康托展开从二维转换到一维(由二维转换到一维可以用for循环初始化数组使得二维转换成一维)

#include<bits/stdc++.h>

using namespace std;

#define ll long long
#define PII pair<int, int>
#define PLL pair<ll, ll>

const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps = 1e-8;
int dx[4] = {-1,0,1,0},dy[4] = {0,1,0,-1};
int n,m;
int bfs(string start)
{
    string end = "12345678x";
    queue<string>q;
    unordered_map<string ,int> d;
    q.push(start);
    d[start] = 0;
    while(q.size())
    {
        auto t = q.front();
        q.pop();

        int distance = d[t];
        if(t == end) return distance ;

        int k = t.find('x');
        int x = k / 3, y = k % 3;//非常nb的一维转化成2维

        for(int i = 0 ; i < 4; i ++)
        {
            int a = x + dx[i];
            int b = y + dy[i];
            if(a >= 0 && a < 3 && b >= 0 && b < 3)
            {
                swap(t[k],t[a * 3 + b]);
                
                if(!d.count(t))
                {
                    d[t] = distance + 1;
                    q.push(t);
                }
                swap(t[k],t[a * 3 + b]);
                //还原这个状态,为走下一次做准备
            }
        }
    }
    return -1;
}

int main()
{
    string start;
    for(int i = 0; i < 9; i ++)
    {
        char c;
        cin >> c;
        start += c;
    }
    cout<<bfs(start)<<endl;

    system("pause");
    return 0;
}

1107. 魔板 - AcWing题库

思路:多种变换的八数码,按照所述进行暴搜即可

注意!:哥们间断性wa了3天才发现是从12345678变到输入而不是输入变到12345678

#include<bits/stdc++.h>

using namespace std;

#define ll long long
#define PII pair<char, string >
#define PLL pair<ll, ll>

const int N = 1e6 + 10;
const int M = 2 * N;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps = 1e-8;

string start,endt;
unordered_map<string,PII>pre;
unordered_map<string,int>dist;
string get(string s,int t)
{
    string res = s;
    if(t == 0) res = {s[7],s[6],s[5],s[4],s[3],s[2],s[1],s[0]};
    if(t == 1) res = {s[3],s[0],s[1],s[2],s[5],s[6],s[7],s[4]};
    if(t == 2) res = {s[0],s[6],s[1],s[3],s[4],s[2],s[5],s[7]};
    return res;
}
void bfs(string start)
{
    dist[start] = 0;
    queue<string>q;
    
    q.push(start);
    
    while(q.size())
    {
        auto t = q.front();
        q.pop();

        if(t == endt) return;
        for(int i = 0; i < 3; i ++)
        {
            string s = get(t,i);
            if(!dist.count(s))
            {
                dist[s] = dist[t] + 1;
                pre[s] = {char(i + 'A'),t};
                if(s == endt) return;
                q.push(s);
            }
        }
    }
}
void solve()
{
    for(int i = 0; i < 8; i ++)
    {
        char c;
        cin >> c;
        endt += c;
    }
    start = "12345678";
    bfs(start);
    cout << dist[endt] << endl;
    string ans;
    
    while(start != endt)
    {
        ans += pre[endt].first;
        endt = pre[endt].second;
    }
    reverse(ans.begin(),ans.end());
    if(ans.size())  cout << ans << endl;

}
int main()
{
    solve();



    system("pause");
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值