提供一种题解中没有的优先队列做法:

P1649 [USACO07OCT] Obstacle Course S

AC_love @ 2023-09-06 14:08:15

题解里只有两篇用到了 priority_queue,都是用的优先队列优化的 Dij 算法,都是这道题其实可以不用 Dij,直接用优先队列来解决。

思路类似洪水填充,优先搜索不需要转弯的情况,这样的话最早搜到的就是答案。

#include <bits/stdc++.h>
using namespace std;

struct p
{
    int x;
    int y;
    int t;
    int d;
    bool operator < (const p &x) const
    {
        return x.t < t;
    }
};
priority_queue <p> q;

int n;
char c[114][114];
int dis[114][114];

int bx, by;

int dx[5] = {0, 0,  0, 1, -1};
int dy[5] = {0, 1, -1, 0,  0};

void bfs()
{
    while(q.empty() == 0)
    {
        p t = q.top();
        q.pop();
        if(t.t > dis[t.x][t.y])
            continue;
        dis[t.x][t.y] = t.t;
        if(c[t.x + dx[t.d]][t.y + dy[t.d]] == '.')
            q.push(p{t.x + dx[t.d], t.y + dy[t.d], t.t, t.d});
        for(int i = 1; i <= 4; i = i + 1)
        {
            if(i == t.d)
                continue;
            if(c[t.x + dx[i]][t.y + dy[i]] == '.')
                q.push(p{t.x + dx[i], t.y + dy[i], t.t + 1, i});
        }
    }
}

int main()
{
    cin >> n;
    memset(dis, 0x3f3f3f, sizeof(dis));
    for(int i = 1; i <= n; i = i + 1)
        for(int j = 1; j <= n; j = j + 1)
        {
            cin >> c[i][j];
            if(c[i][j] == 'A')
            {
                q.push(p{i, j, 0, 1});
                q.push(p{i, j, 0, 2});
                q.push(p{i, j, 0, 3});
                q.push(p{i, j, 0, 4});
                dis[i][j] = 0;
            }
            if(c[i][j] == 'B')
            {
                bx = i;
                by = j;
                c[i][j] = '.';
            }
        }
    bfs();
    if(dis[bx][by] != 1061109567)
        cout << dis[bx][by];
    else
        cout << -1;
    return 0;
}

by AC_love @ 2023-09-06 14:11:17

思路借鉴了 P4667


by Libingyue2011 @ 2024-02-04 11:58:04

可以再优化,用双向队列广搜。


|