Codeforces Round #829 (Div. 2) F // 最短路

题目来源:Codeforces Round #829 (Div. 2) F - The Beach

题目链接:Problem - F - Codeforces


题意

给定一个n×m的网格,其中'#'代表障碍,'.'代表空地,成对出现的'U'、'D'表示一张竖放的椅子,成对出现的'L'、'R'表示一张横放的椅子。

有两种操作:以椅子所在的其中一个格子为端点,旋转90°,花费代价p;将竖放的椅子整体上/下移动一格,或将横放的椅子整体左/右移动一格,花费代价q。操作合法,当且仅当:操作后椅子新占用的那个格子在网格内,且进行该次操作前为空地。

要求:输出进行若干操作后,网格中能放下一张新椅子所需要的最小总代价;若无论如何都放不下新椅子,输出1

数据范围:1n3·1051m3·1051n·m3·1051p,q109.

思路:最短路

将每个格子视作一个节点。

再建一个虚拟源点0,记所有点到源点的最短距离为disti,表示点i变为空地所需要的最小代价。

对于原本就是空地的格子x,其变为空地的代价为0,因此由虚拟源点0往该格子建单向边,00x.

每进行一次操作,实际上是将某格空地x转移到某格椅子y上,y变为空地的代价为min(dist[y],dist[x]+p/q),因此可以建一条单向边,xp/qy.

跑一遍Dijkstra,得到源点到所有点的最短距离。

那么要找到放椅子的地方,实际上是要找到连续的两个格子ij,使得这两格子都为空地,其所需要的最小总代价为disti+distj.

时间复杂度:O(nm·lognm).

代码

#include <bits/stdc++.h>
#define endl '\n'
#define LL long long
#define PII pair<int,int>
#define PLI pair<LL,int>
using namespace std;

const int N = 300010;
const LL INF = 0x3f3f3f3f3f3f3f3f;

int n, m, p, q, st[N];
LL dist[N];
vector<PII> g[N];
char s[N];

void add(int i, int j, int v, int w)
{
    if(i < 1 || i > n || j < 1 || j > m) return;
    int u = (i - 1) * m + j;
    g[u].push_back({v, w});
}

void dijkstra()
{
    memset(dist, 0x3f, sizeof dist);
    dist[0] = 0;

    priority_queue<PLI, vector<PLI>, greater<PLI>> heap;
    heap.push({0, 0});

    while(heap.size()) {
        auto t = heap.top();
        heap.pop();

        int u = t.second;
        if(st[u]) continue;
        st[u] = true;

        for(auto p : g[u]) {
            int v = p.first, w = p.second;
            if(dist[v] > dist[u] + w) {
                dist[v] = dist[u] + w;
                heap.push({dist[v], v});
            }
        }
    }
}

int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);

    cin >> n >> m >> p >> q;

    for(int i = 1; i <= n; ++ i) {
        cin >> s + 1;
        for(int j = 1; j <= m; ++ j) {
            int ver = (i - 1) * m + j;
            if(s[j] == '.') {
                g[0].push_back({ver, 0});
            } else if(s[j] == 'U') {
                add(i + 1, j - 1, ver, p), add(i + 1, j + 1, ver, p);
                add(i + 2, j, ver, q);
            } else if(s[j] == 'D') {
                add(i - 1, j - 1, ver, p), add(i - 1, j + 1, ver, p);
                add(i - 2, j, ver, q);
            } else if(s[j] == 'L') {
                add(i - 1, j + 1, ver, p), add(i + 1, j + 1, ver, p);
                add(i, j + 2, ver, q);
            } else if(s[j] == 'R') {
                add(i - 1, j - 1, ver, p), add(i + 1, j - 1, ver, p);
                add(i, j - 2, ver, q);
            }
        }
    }

    dijkstra();

    LL ans = INF;
    for(int i = 1; i <= n; ++ i) {
        for(int j = 1; j <= m; ++ j) {
            int u = (i - 1) * m + j;
            if(i < n) {
                int v = i * m + j;
                ans = min(ans, dist[u] + dist[v]);
            }
            if(j < m) {
                int v = (i - 1) * m + j + 1;
                ans = min(ans, dist[u] + dist[v]);
            }
        }
    }
    cout << (ans < INF ? ans : -1) << endl;

    return 0;
}
posted @   Jakon  阅读(261)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示