Cod sursa(job #1211488)

Utilizator andreiiiiPopa Andrei andreiiii Data 22 iulie 2014 18:13:50
Problema Coduri Huffman Scor 70
Compilator cpp Status done
Runda Arhiva educationala Marime 3.35 kb
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

class Huffman {
public:
    Huffman(const int _Base = 0, const vector<int> &_Values = vector<int>()):
        Base(_Base),
        OriginalSize(_Values.size()),
        Size(GetSize(Base, _Values.size())),
        Cost(0LL),
        Nodes(vector<Node>(Size, Node(0, Base)))
        {
            queue< pair<int, long long> > Q1, Q2;

            for (int i = 0; i < OriginalSize; i++)
                Nodes[i].value = _Values[i];

            for (int i = 0; i < Size; i++)
                Q1.push(make_pair(i, Nodes[i].value));

            while (int(Q1.size() + Q2.size()) >= Base)
            {
                Size++;
                Nodes.push_back(Node(0, Base));

                for (int i = 0; i < Base; i++)
                {
                    if (!Q1.empty() && (Q2.empty() || Q1.front().second < Q2.front().second))
                    {
                        Nodes.back().value += Q1.front().second;
                        Nodes.back().sons[i] = Q1.front().first;
                        Q1.pop();
                    }
                    else
                    {
                        Nodes.back().value += Q2.front().second;
                        Nodes.back().sons[i] = Q2.front().first;
                        Q2.pop();
                    }
                }

                Q2.push(make_pair(Size - 1, Nodes.back().value));
                Cost += Nodes.back().value;
            }
        }

    vector< pair<int, long long> > getStrings() const {
        queue< pair<int, pair<long long, int>> > Q;
        Q.push(make_pair(Size - 1, make_pair(0, 0)));

        vector< pair<int, long long> > ret(OriginalSize);

        while (!Q.empty())
        {
            const int node = Q.front().first, level = Q.front().second.second;
            const long long code = Q.front().second.first;
            Q.pop();

            int Psize = GetSize(Base, OriginalSize);
            if (node < Psize)
            {
                if (node < OriginalSize)
                    ret[node] = make_pair(level, code);

                continue;
            }

            for (int i = 0; i < Base; i++)
                Q.push(make_pair(Nodes[node].sons[i], make_pair(code * Base + i, level + 1)));
        }

        return ret;
    }

    int size() const {
        return OriginalSize;
    }

    int actual_size() const {
        return Size;
    }

    long long cost() const {
        return Cost;
    }

private:
    class Node {
    public:
        long long value;
        vector<int> sons;

        Node(const long long _value = 0, const int sons_count = 0):
            value(_value),
            sons(vector<int>(sons_count, 0)) {}
    };

    int Base;
    int OriginalSize, Size;
    long long Cost;
    vector<Node> Nodes;

    static int GetSize(const int Base, const int Size) {
        return (Size - 3 + Base) / (Base - 1) * (Base - 1) + 1;
    }
};

int main()
{
    freopen("huffman.in", "r", stdin);
    freopen("huffman.out", "w", stdout);

    int N;
    scanf("%d", &N);

    vector<int> Values(N);
    for (int i = 0; i < int(Values.size()); i++)
        scanf("%d", &Values[i]);

    Huffman T = Huffman(2, Values);

    printf("%lld\n", T.cost());

    vector< pair<int, long long> > Ans = T.getStrings();

    for (const auto p: Ans)
        printf("%d %lld\n", p.first, p.second);
}