Cod sursa(job #1211522)

Utilizator andreiiiiPopa Andrei andreiiii Data 22 iulie 2014 19:13:05
Problema Coduri Huffman Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 3.64 kb
#include <algorithm>
#include <cstdio>
#include <vector>
#include <queue>

using namespace std;

class FileInput {
    public:
        FileInput() {}
        FileInput(const char *filename) {
            file = fopen(filename, "r");
            fread(buffer, BUFFER_SIZE, 1, file);
            cursor = 0;
        }
        inline FileInput & operator >> (int &n) {
            while(buffer[cursor] == ' ' || buffer[cursor] == '\n') {
                advance();
            }
            n = 0;
            while(isdigit(buffer[cursor])) {
                n = n * 10 + buffer[cursor] - '0';
                advance();
            }
            return *this;
        }
    private:
        static const int BUFFER_SIZE = 1 << 19;
        FILE* file;
        char buffer[BUFFER_SIZE];
        int cursor;
        inline void advance() {
            ++ cursor;
            if(cursor == BUFFER_SIZE) {
                cursor = 0;
                fread(buffer, BUFFER_SIZE, 1, file);
            }
        }
} fin("huffman.in");

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),
        G(vector< vector<int> > (Size, vector<int>()))
        {
            vector<long long> Q(Size, 0);

            for (int i = 0; i < OriginalSize; i++)
                Q[i + Size - OriginalSize] = _Values[i];

            int left1 = 0, left2 = Size;
            const int Psize = Size;

            while (Psize - left1 + Size - left2 >= Base)
            {
                G.push_back(vector<int>(Base));

                long long value = 0;
                for (int i = 0; i < Base; i++)
                {
                    if (left1 < Psize && (left2 >= Size || Q[left1] < Q[left2]))
                    {
                        value += Q[left1];
                        G.back()[i] = left1;
                        left1++;
                    }
                    else
                    {
                        value += Q[left2];
                        G.back()[i] = left2;
                        left2++;
                    }
                }

                Q.push_back(value);
                Cost += value;
                Size++;
            }
        }

    vector< pair<int, long long> > getCoding() const {

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

        Dfs(ret, Size - 1, 0, 0);

        return ret;
    }

    int size() const {
        return OriginalSize;
    }

    int actual_size() const {
        return Size;
    }

    long long cost() const {
        return Cost;
    }

private:

    int Base;
    int OriginalSize, Size;
    long long Cost;
    vector< vector<int> > G;

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

    void Dfs(vector< pair<int, long long> > &Codes, const int node, const long long code, const int level) const
    {
        if (node < GetSize(Base, OriginalSize))
        {
            if (node < OriginalSize)
                Codes[node] = make_pair(level, code);

            return;
        }

        for (int i = 0; i < Base; i++)
            Dfs(Codes, G[node][i], code * Base + i, level + 1);
    }
};

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

    int N;
    fin >> N;

    vector<int> Values(N);
    for (int i = 0; i < int(Values.size()); i++)
        fin >> Values[i];

    Huffman T = Huffman(2, Values);

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

    vector< pair<int, long long> > Codes = T.getCoding();

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