【搜索】—— 多源BFS + 最小步数模型

【搜索】—— 多源BFS + 最小步数模型_第1张图片


AcWing 173. 矩阵距离  (多源BFS)

【搜索】—— 多源BFS + 最小步数模型_第2张图片 

输入样例:

3 4
0001
0011
0110

输出样例:

3 2 1 0
2 1 0 0
1 0 0 1

多源最短路的问题中,如果我们采用每个点的单源最短路,很大概率会超时 

所以我们需要用到一个 “超级源点” 思想

【搜索】—— 多源BFS + 最小步数模型_第3张图片

建立一个虚拟源点将所有的起点和这个虚拟源点连一条边为 0 的边,然后展开单源最短路 

【搜索】—— 多源BFS + 最小步数模型_第4张图片


#include 
#include 
#include 

using namespace std;

#define x first
#define y second

const int N = 1010, M = N * N;

typedef pair PII;

int n, m;
char g[N][N];
PII q[M];
int dist[N][N];

void bfs()
{
    memset(dist, -1, sizeof dist);
    
    int hh = 0, tt = -1;
    for(int i = 0; i < n; i ++ )
        for(int j = 0; j < m; j ++ )
        if(g[i][j] == '1')
        {
            dist[i][j] = 0;
            q[ ++ tt] = {i, j};
        }
    
    int dx[] = {1, 0, -1, 0}, dy[] = {0, 1, 0, -1};
    
    while(hh <= tt)
    {
        auto t = q[hh ++ ];
        for(int i = 0; i < 4; i ++ )
        {
            int a = t.x + dx[i], b = t.y + dy[i];
            if(a < 0 || a >= n || b < 0 || b >= m) continue;
            if(dist[a][b] != -1) continue;
            
            dist[a][b] = dist[t.x][t.y] + 1;
            q[++ tt] = {a, b};
        }
    }
}

int main()
{
    cin >> n >> m;
    for(int i = 0; i < n; i ++ ) scanf("%s", g[i]);
    
    bfs();
    
    for(int i = 0; i < n; i ++ )
    {
        for(int j = 0; j < m; j ++ )
            printf("%d ", dist[i][j]);
        cout << endl;
    }
    
    return 0;
        
}

 AcWing 1107. 魔板(最小步数模型)

【搜索】—— 多源BFS + 最小步数模型_第5张图片

 

输入样例:

2 6 8 4 5 7 3 1

输出样例:

7
BCABCCB

这是将整个棋盘看做是一个状态,通过不同的操作来实现状态间的转移 

存放一个状态,我们使用的是哈希法 \small \rightarrow 


#include 
#include 
#include 
#include 
#include 

using namespace std;

char g[2][4];
unordered_map> pre;
unordered_map dist;

void set(string state)
{
    for (int i = 0; i < 4; i ++ ) g[0][i] = state[i];
    for (int i = 7, j = 0; j < 4; i --, j ++ ) g[1][j] = state[i];
}

string get()
{
    string res;
    for (int i = 0; i < 4; i ++ ) res += g[0][i];
    for (int i = 3; i >= 0; i -- ) res += g[1][i];
    return res;
}

string move0(string state)
{
    set(state);
    for (int i = 0; i < 4; i ++ ) swap(g[0][i], g[1][i]);
    return get();
}

string move1(string state)
{
    set(state);
    int v0 = g[0][3], v1 = g[1][3];
    for (int i = 3; i >= 0; i -- )
    {
        g[0][i] = g[0][i - 1];
        g[1][i] = g[1][i - 1];
    }
    g[0][0] = v0, g[1][0] = v1;
    return get();
}

string move2(string state)
{
    set(state);
    int v = g[0][1];
    g[0][1] = g[1][1];
    g[1][1] = g[1][2];
    g[1][2] = g[0][2];
    g[0][2] = v;
    return get();
}

int bfs(string start, string end)
{
    if (start == end) return 0;

    queue q;
    q.push(start);
    dist[start] = 0;

    while (!q.empty())
    {
        auto t = q.front();
        q.pop();

        string m[3];
        m[0] = move0(t);
        m[1] = move1(t);
        m[2] = move2(t);

        for (int i = 0; i < 3; i ++ )
            if (!dist.count(m[i]))
            {
                dist[m[i]] = dist[t] + 1;
                pre[m[i]] = {'A' + i, t};
                q.push(m[i]);
                if (m[i] == end) return dist[end];
            }
    }

    return -1;
}

int main()
{
    int x;
    string start, end;
    for (int i = 0; i < 8; i ++ )
    {
        cin >> x;
        end += char(x + '0');
    }

    for (int i = 1; i <= 8; i ++ ) start += char('0' + i);

    int step = bfs(start, end);

    cout << step << endl;

    string res;
    while (end != start)
    {
        res += pre[end].first;
        end = pre[end].second;
    }

    reverse(res.begin(), res.end());

    if (step > 0) cout << res << endl;

    return 0;
}

AcWing 175. 电路维修 (双端队列广搜)

【搜索】—— 多源BFS + 最小步数模型_第6张图片

输入样例:

1
3 5
\\/\\
\\///
/\\\\

输出样例:

1

 【搜索】—— 多源BFS + 最小步数模型_第7张图片

 


【搜索】—— 双端队列广搜_玄澈_的博客-CSDN博客_双端队列搜索 

 


#include
#include
#include
#include

#define x first
#define y second
using namespace std;
typedef pair PII;
const int N = 510;

int n,m;
char g[N][N];
int dist[N][N];;
deque q;

int bfs()
{
    memset(dist,0x3f,sizeof dist);
    q.push_front({0,0});
    dist[0][0]=0;
    int dx[]={-1,-1,1,1},dy[]={-1,1,1,-1};
    int ix[]={-1,-1,0,0},iy[]={-1,0,0,-1};

    char s[]="\\/\\/";

    while(q.size())
    {
        PII t=q.front();
        q.pop_front();
        for(int i=0;i<4;i++)
        {
            int a=t.x+dx[i],b=t.y+dy[i];
            int aa=t.x+ix[i],bb=t.y+iy[i];
            if(a<0||a>n||b<0||b>m) continue;
            int d = dist[t.x][t.y]+(g[aa][bb]!=s[i]);
            if (d < dist[a][b])
            {
                dist[a][b] = d;

                if (g[aa][bb] != s[i]) q.push_back({a, b});
                else q.push_front({a, b});
            }
        }
    }
    return dist[n][m];
}


int main()
{   int T;
    scanf("%d", &T);
    while (T -- )
    {
        scanf("%d%d", &n, &m);
        for (int i = 0; i < n; i ++ ) scanf("%s", g[i]);
        if((n+m)%2==1) 
        {
            puts("NO SOLUTION");
            continue;
        }                
        cout<

你可能感兴趣的:(ACM算法笔记,#,ACM算法-搜索,宽度优先,算法,bfs,蓝桥杯,c++)