#pragma once

#include <vector>
#include <utility>
#include <string>

typedef std::pair<int, int> Position;

extern const int EMPTY;
extern const Position UNKNOWN;

std::vector<std::vector<int>> heights_to_mat(const std::vector<int>& heights, int H);

class State {
public:
    std::vector<std::vector<int>> bay;
    std::vector<int> heights;
    int H, W, n, max_ind;
    std::vector<Position> position;

    State(std::vector<std::vector<int>> _bay, std::vector<int> _heights, int _H, int _max_ind);

    State copy() const;
    int top(int i) const;
    void move(int i, int j);
    void retrieve(int i);
    void add(int i, int x);
    std::pair<int, int> get_position(int x) const;
    void print_bay();

    class Ordered_State apply_order(const std::vector<int>& order);
};

class Ordered_State : public State {
public:
    int min_container;
    Ordered_State();

    void retrieve(int i);
    void add(int i, int x);
    bool operator==(const Ordered_State& other) const;
    std::string to_string() const;
};

int opt(State& s);
double ratios(State& ref_s, State& s, int cost, std::vector<int>& order, Position req);