Submission #1025976

#TimeUsernameProblemLanguageResultExecution timeMemory
1025976model_codeText editor (CEOI24_editor)C++17
56 / 100
2218 ms1048576 KiB
// Author: Benjamin Swart
#include <algorithm>
#include <cstdint>
#include <iostream>
#include <queue>
#include <vector>

typedef uint64_t u64;

struct node;

struct edge {
    u64 length;
    node *target;

    edge(u64 length, node *target) : length(length), target(target) {}
};

struct node {
    std::vector<edge> edges;
    bool visited = false;
};

struct coords {
    u64 row;
    u64 col;

    constexpr coords(u64 row, u64 col) : row(row), col(col) {}
    constexpr coords() : row(0), col(0) {}
};

struct compressor {
    std::vector<u64> values;

    void build() {
        std::sort(values.begin(), values.end());
        auto end = std::unique(values.begin(), values.end());
        values.erase(end, values.end());
    }

    u64 compress(u64 value) {
        return std::lower_bound(values.begin(), values.end(), value) - values.begin();
    }

    u64 decompress(u64 value) {
        return values[value];
    }
};

std::pair<node *, node *> build_graph(std::vector<u64> lines, coords start, coords end) {
    compressor com = {lines};
    com.values.push_back(start.col);
    com.values.push_back(end.col);
    com.values.push_back(0);
    com.build();

    std::vector<std::vector<node *>> nodes;

    for (u64 length : lines) {
        std::vector<node *> line;

        node *last = new node;
        line.push_back(last);

        u64 com_length = com.compress(length);

        for (u64 i = 0; i < com_length; i++) {
            node *curr = new node;
            line.push_back(curr);

            u64 diff = com.decompress(i + 1) - com.decompress(i);

            curr->edges.push_back(edge(diff, last));
            last->edges.push_back(edge(diff, curr));

            last = curr;
        }

        nodes.push_back(line);
    }

    for (u64 line = 0; line < nodes.size(); line++) {
        for (u64 col = 0; col < nodes[line].size(); col++) {
            if (line > 0) {
                u64 other_col = std::min(col, nodes[line - 1].size() - 1);
                nodes[line][col]->edges.push_back(edge(1, nodes[line - 1][other_col]));
            }

            if (line < nodes.size() - 1) {
                u64 other_col = std::min(col, nodes[line + 1].size() - 1);
                nodes[line][col]->edges.push_back(edge(1, nodes[line + 1][other_col]));
            }
        }
    }

    for (u64 line = 0; line < nodes.size() - 1; line++) {
        nodes[line].back()->edges.push_back(edge(1, nodes[line + 1].front()));
        nodes[line + 1].front()->edges.push_back(edge(1, nodes[line].back()));
    }

    return {nodes[start.row][com.compress(start.col)], nodes[end.row][com.compress(end.col)]};
}

typedef std::pair<u64, node *> node_info;

u64 find_path(node *start, node *end) {
    std::priority_queue<node_info, std::vector<node_info>, std::greater<node_info>> queue;

    queue.push({0, start});

    while (!queue.empty()) {
        auto [dist, n] = queue.top();
        queue.pop();

        if (n->visited)
            continue;

        n->visited = true;

        if (n == end)
            return dist;

        for (edge e : n->edges) {
            queue.push({dist + e.length, e.target});
        }
    }

    return -1;
}

int main() {
    std::cin.exceptions(std::cin.badbit | std::cin.failbit);

    u64 line_count;
    std::cin >> line_count;

    coords start;
    coords end;

    std::cin >> start.row >> start.col;
    std::cin >> end.row >> end.col;

    start.row--;
    start.col--;
    end.row--;
    end.col--;

    std::vector<u64> lines;
    lines.reserve(line_count);

    for (u64 i = 0; i < line_count; i++) {
        u64 length;
        std::cin >> length;

        lines.push_back(length);
    }

    auto nodes = build_graph(lines, start, end);
    std::cout << find_path(nodes.first, nodes.second) << std::endl;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...