Cod sursa(job #2551636)

Utilizator preda.andreiPreda Andrei preda.andrei Data 20 februarie 2020 00:57:04
Problema Coduri Huffman Scor 95
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.32 kb
#include <cstdint>
#include <fstream>
#include <queue>
#include <vector>

using namespace std;

struct Code
{
    int length;
    int64_t num;
};

struct Node
{
    int id;
    int cost = 0;
    int symbol = -1;
    int zero = -1;
    int one = -1;

    Node(int id, int cost, int symbol = -1)
        : id(id), cost(cost), symbol(symbol) {}
};

using Tree = vector<Node>;

int PopCheapest(queue<int> &q1, queue<int> &q2, const Tree &tree)
{
    int res = -1;
    if (q1.empty() || (!q2.empty() && tree[q2.front()].cost < tree[q1.front()].cost)) {
        res = q2.front();
        q2.pop();
    } else {
        res = q1.front();
        q1.pop();
    }
    return res;
}

void Dfs(const Tree &tree, int node, int length, int64_t num, vector<Code> &codes, int64_t &cost)
{
    if (tree[node].symbol >= 0) {
        codes[tree[node].symbol] = (Code){.length = length, .num = num};
        cost += 1LL * length * tree[node].cost;
    }

    if (tree[node].zero >= 0) {
        Dfs(tree, tree[node].zero, length + 1, (num << 1), codes, cost);
    }
    if (tree[node].one >= 0) {
        Dfs(tree, tree[node].one, length + 1, (num << 1) + 1, codes, cost);
    }
}

vector<Code> ExtractCodes(const Tree &tree, int root, int symbols, int64_t &cost)
{
    vector<Code> codes(symbols);
    Dfs(tree, root, 0, 0, codes, cost);
    return codes;
}

vector<Code> FindCodes(const vector<int> &count, int64_t &cost)
{
    queue<int> q1, q2;
    Tree tree;

    for (size_t i = 0; i < count.size(); i += 1) {
        tree.push_back(Node(i, count[i], i));
        q1.push(i);
    }

    while (q1.size() + q2.size() > 1) {
        auto a = PopCheapest(q1, q2, tree);
        auto b = PopCheapest(q1, q2, tree);
        auto cost = tree[a].cost + tree[b].cost;

        tree.push_back(Node(tree.size(), cost));
        tree.back().zero = a;
        tree.back().one = b;
        q2.push(tree.size() - 1);
    }
    return ExtractCodes(tree, q2.front(), count.size(), cost);
}

int main()
{
    ifstream fin("huffman.in");
    ofstream fout("huffman.out");

    int symbols;
    fin >> symbols;

    vector<int> count(symbols);
    for (auto &c : count) {
        fin >> c;
    }

    int64_t length = 0;
    auto codes = FindCodes(count, length);

    fout << length << "\n";
    for (const auto &code : codes) {
        fout << code.length << " " << code.num << "\n";
    }

    return 0;
}