cpp_library

This documentation is automatically generated by online-judge-tools/verification-helper

This project is maintained by tsutaj

:warning: chokudai サーチ
(marathon/chokudai_search.cpp)

AHC032 で利用実績あり。
https://atcoder.jp/contests/ahc032/submissions/61302590

Depends on

Code

/**
 * @brief chokudai サーチ
 * @docs docs/marathon/chokudai_search.md
 */

#include "interval_heap.cpp"

template <class State, class Timer>
class ChokudaiSearch {
   public:
    ChokudaiSearch() : num_iter_(-1) {}
    void init(int max_turns, double search_time, int time_check_iter) {
        states_.resize(max_turns + 1);
        search_time_ = search_time;
        num_iter_ = 0;
        time_check_iter_ = time_check_iter;
        max_num_states_.resize(max_turns, 1 << 30);
    }
    void set_max_num_states(int max_num_state) {
        fill(max_num_states_.begin(), max_num_states_.end(), max_num_state);
    }
    void set_max_num_states(const vector<int> &max_num_states) {
        assert(max_num_states.size() == max_num_states_.size());
        max_num_states_ = max_num_states;
    }
    void register_state(int turns, const State &state) {
        states_[turns].emplace(state);
        while(states_[turns].size() > max_num_states_[turns]) {
            states_[turns].pop_max();
        }
    }
    void search(Timer &timer, const auto &add_next_states) {
        assert(num_iter_ >= 0);
        const double start_time = timer.getTime();
        for(num_iter_ = 0;; num_iter_++) {
            for(int turns = 0; turns + 1 < (int)states_.size(); turns++) {
                if(timer.getTime() - start_time > search_time_) {
                    goto TIME_OVER;
                }
                if(states_[turns].size() == 0) continue;
                State state = states_[turns].top_min();
                states_[turns].pop_min();
                add_next_states(turns, state);
            }
        }
    TIME_OVER:;
        fprintf(stderr, "chokudai search: num_iter = %d\n", num_iter_);
    }
    const State &get_best_state() const { return states_.back().top_min(); }

   private:
    double search_time_;
    int num_iter_;
    int time_check_iter_;
    vector<IntervalHeap<State>> states_;
    vector<int> max_num_states_;
};
#line 1 "marathon/chokudai_search.cpp"
/**
 * @brief chokudai サーチ
 * @docs docs/marathon/chokudai_search.md
 */

#line 1 "marathon/interval_heap.cpp"
template <typename Tp>
class IntervalHeap {
   public:
    template <class Iterator>
    IntervalHeap(Iterator first, Iterator last) : data_(first, last) {
        make_heap();
    }
    IntervalHeap() = default;

    size_t size() const { return data_.size(); }
    void clear() { data_.clear(); }
    void emplace(const Tp& val) {
        data_.push_back(val);
        up(size() - 1);
    }
    void push(const Tp& val) { emplace(val); }
    const Tp& top_min() const { return data_[size() >= 2]; }
    const Tp& top_max() const { return data_[0]; }
    void pop_min() {
        if(size() <= 2) {
            data_.pop_back();
        } else {
            swap(data_[1], data_.back());
            data_.pop_back();
            const size_t k = down(1);
            up(k);
        }
    }
    void pop_max() {
        if(size() <= 1) {
            data_.pop_back();
        } else {
            swap(data_[0], data_.back());
            data_.pop_back();
            const size_t k = down(0);
            up(k);
        }
    }

   private:
    vector<Tp> data_;
    inline size_t to_k_max(size_t k) { return k & ~1; }
    inline size_t to_k_min(size_t k) { return k | 1; }
    inline size_t get_parent(size_t k, bool is_max) { return (((k >> 1) - 1) & ~1) | (is_max ? 0 : 1); }

    size_t down(size_t k) {
        const size_t s = size();
        if(k & 1) {
            // min heap
            while(true) {
                const size_t cl = (k << 1) + 1;
                const size_t cr = (k << 1) + 3;
                if(cl >= s) break;
                const size_t c = (cr >= s || data_[cl] < data_[cr]) ? cl : cr;
                if(data_[c] < data_[k]) {
                    swap(data_[k], data_[c]);
                    k = c;
                } else {
                    break;
                }
            }
        } else {
            // max heap
            while(true) {
                const size_t cl = (k << 1) + 2;
                const size_t cr = (k << 1) + 4;
                if(cl >= s) break;
                const size_t c = (cr >= s || data_[cr] < data_[cl]) ? cl : cr;
                if(data_[k] < data_[c]) {
                    swap(data_[k], data_[c]);
                    k = c;
                } else {
                    break;
                }
            }
        }
        return k;
    }
    void up(size_t k, size_t root = 1) {
        const size_t k_max = to_k_max(k);
        const size_t k_min = to_k_min(k);
        if(k_min < size() && data_[k_max] < data_[k_min]) {
            swap(data_[k_max], data_[k_min]);
            k ^= 1;
        }

        size_t p;
        // max heap
        while(root < k && data_[p = get_parent(k, true)] < data_[k]) {
            swap(data_[k], data_[p]);
            k = p;
        }
        // min heap
        while(root < k && data_[k] < data_[p = get_parent(k, false)]) {
            swap(data_[k], data_[p]);
            k = p;
        }
    }
    void make_heap() {
        for(size_t i = size(); i--;) {
            if((i & 1) && data_[i - 1] < data_[i]) {
                swap(data_[i - 1], data_[i]);
            }
            size_t k = down(i);
            up(k, i);
        }
    }
};
#line 7 "marathon/chokudai_search.cpp"

template <class State, class Timer>
class ChokudaiSearch {
   public:
    ChokudaiSearch() : num_iter_(-1) {}
    void init(int max_turns, double search_time, int time_check_iter) {
        states_.resize(max_turns + 1);
        search_time_ = search_time;
        num_iter_ = 0;
        time_check_iter_ = time_check_iter;
        max_num_states_.resize(max_turns, 1 << 30);
    }
    void set_max_num_states(int max_num_state) {
        fill(max_num_states_.begin(), max_num_states_.end(), max_num_state);
    }
    void set_max_num_states(const vector<int> &max_num_states) {
        assert(max_num_states.size() == max_num_states_.size());
        max_num_states_ = max_num_states;
    }
    void register_state(int turns, const State &state) {
        states_[turns].emplace(state);
        while(states_[turns].size() > max_num_states_[turns]) {
            states_[turns].pop_max();
        }
    }
    void search(Timer &timer, const auto &add_next_states) {
        assert(num_iter_ >= 0);
        const double start_time = timer.getTime();
        for(num_iter_ = 0;; num_iter_++) {
            for(int turns = 0; turns + 1 < (int)states_.size(); turns++) {
                if(timer.getTime() - start_time > search_time_) {
                    goto TIME_OVER;
                }
                if(states_[turns].size() == 0) continue;
                State state = states_[turns].top_min();
                states_[turns].pop_min();
                add_next_states(turns, state);
            }
        }
    TIME_OVER:;
        fprintf(stderr, "chokudai search: num_iter = %d\n", num_iter_);
    }
    const State &get_best_state() const { return states_.back().top_min(); }

   private:
    double search_time_;
    int num_iter_;
    int time_check_iter_;
    vector<IntervalHeap<State>> states_;
    vector<int> max_num_states_;
};
Back to top page