結果

問題 No.5020 Averaging
ユーザー komasandesukomasandesu
提出日時 2024-02-25 16:42:39
言語 C++23
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 937 ms / 1,000 ms
コード長 5,435 bytes
コンパイル時間 2,062 ms
コンパイル使用メモリ 150,960 KB
実行使用メモリ 57,592 KB
スコア 27,794,270
最終ジャッジ日時 2024-02-25 16:45:06
合計ジャッジ時間 48,866 ms
ジャッジサーバーID
(参考情報)
judge14 / judge15
純コード判定しない問題か言語
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 856 ms
57,208 KB
testcase_01 AC 937 ms
56,696 KB
testcase_02 AC 909 ms
57,336 KB
testcase_03 AC 905 ms
57,412 KB
testcase_04 AC 893 ms
57,464 KB
testcase_05 AC 877 ms
57,464 KB
testcase_06 AC 913 ms
57,336 KB
testcase_07 AC 852 ms
57,592 KB
testcase_08 AC 915 ms
56,824 KB
testcase_09 AC 886 ms
57,336 KB
testcase_10 AC 859 ms
57,208 KB
testcase_11 AC 870 ms
56,824 KB
testcase_12 AC 878 ms
56,696 KB
testcase_13 AC 864 ms
56,700 KB
testcase_14 AC 836 ms
57,400 KB
testcase_15 AC 931 ms
57,592 KB
testcase_16 AC 901 ms
56,696 KB
testcase_17 AC 851 ms
57,336 KB
testcase_18 AC 876 ms
57,464 KB
testcase_19 AC 919 ms
55,544 KB
testcase_20 AC 844 ms
57,336 KB
testcase_21 AC 919 ms
57,336 KB
testcase_22 AC 859 ms
56,696 KB
testcase_23 AC 927 ms
57,208 KB
testcase_24 AC 853 ms
57,336 KB
testcase_25 AC 914 ms
57,080 KB
testcase_26 AC 879 ms
57,336 KB
testcase_27 AC 861 ms
56,568 KB
testcase_28 AC 843 ms
56,704 KB
testcase_29 AC 909 ms
57,336 KB
testcase_30 AC 886 ms
57,336 KB
testcase_31 AC 856 ms
57,592 KB
testcase_32 AC 890 ms
57,336 KB
testcase_33 AC 899 ms
56,824 KB
testcase_34 AC 844 ms
57,208 KB
testcase_35 AC 881 ms
56,696 KB
testcase_36 AC 873 ms
56,824 KB
testcase_37 AC 861 ms
57,336 KB
testcase_38 AC 887 ms
56,824 KB
testcase_39 AC 924 ms
57,208 KB
testcase_40 AC 895 ms
57,336 KB
testcase_41 AC 880 ms
57,464 KB
testcase_42 AC 875 ms
57,464 KB
testcase_43 AC 880 ms
57,464 KB
testcase_44 AC 857 ms
56,184 KB
testcase_45 AC 909 ms
56,824 KB
testcase_46 AC 899 ms
55,416 KB
testcase_47 AC 869 ms
55,416 KB
testcase_48 AC 854 ms
57,336 KB
testcase_49 AC 901 ms
55,672 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// Copyright [2022] <Copyright Eita Aoki (Thunder) >
// 本書のサンプルゲーム以外でも時間制限付きビームサーチをするためにコピー&ペーストで使えるサンプルコード
#include <string>
#include <sstream>
#include <random>
#include <iostream>
#include <queue>
#include <chrono>
#include <utility>
#include <vector>
using namespace std;

int N;
long long A[59];
long long B[59];

const long long avg = 500000000000000000;

// 時間を管理するクラス
class TimeKeeper
{
private:
    std::chrono::high_resolution_clock::time_point start_time_;
    int64_t time_threshold_;

public:
    // 時間制限をミリ秒単位で指定してインスタンスをつくる。
    TimeKeeper(const int64_t &time_threshold)
        : start_time_(std::chrono::high_resolution_clock::now()),
          time_threshold_(time_threshold)
    {
    }

    // インスタンス生成した時から指定した時間制限を超過したか判定する。
    bool isTimeOver() const
    {
        auto diff = std::chrono::high_resolution_clock::now() - this->start_time_;
        return std::chrono::duration_cast<std::chrono::milliseconds>(diff).count() >= time_threshold_;
    }
};

std::mt19937 mt_for_action(0);                // 行動選択用の乱数生成器を初期化
using ScoreType = int64_t;                    // ゲームの評価スコアの型を決めておく。
constexpr const ScoreType INF = 1000000000LL; // あり得ないぐらい大きなスコアの例を用意しておく

class State
{
private:
public:
    ScoreType evaluated_score_ = 0; // 探索上で評価したスコア
    vector<pair<int,int>> actions_{};

    vector<pair<long long,long long>> cards_;
    int turn_ = 0;
    State() {}

    // ゲームの終了判定
    bool isDone() const
    {
        return this->turn_ == 50;
    }

    // 探索用の盤面評価をする
    void evaluateScore()
    {
        long long max_diff = 0;
        max_diff = max( abs(avg-cards_[0].first),abs(avg-cards_[0].second) );
        
        this->evaluated_score_ = -max_diff;
    }

    // 指定したactionでゲームを1ターン進める
    void advance(const pair<int,int> action)
    {
        int i = action.first;
        int j = action.second;
        long long avg_card_A = (cards_[i].first+cards_[j].first)/2;
        long long avg_card_B = (cards_[i].second+cards_[j].second)/2;
        cards_[i].first = avg_card_A;
        cards_[j].first = avg_card_A;
        cards_[i].second = avg_card_B;
        cards_[j].second = avg_card_B;

        ++this->turn_;
    }

    // 現在の状況でプレイヤーが可能な行動を全て取得する
    std::vector<pair<int,int>> legalActions() const
    {
        std::vector<pair<int,int>> actions;

        for (int i = 1; i < N; i++) {
            actions.push_back({0,i});
        }

        return actions;
    }

    // // 必要に応じてアンコメント
    // // 現在のゲーム状況を文字列にする
    // std::string toString() const
    // {
    //     return /*(std::string)文字列化されたゲーム状況*/;
    // }
};

// 探索時のソート用に評価を比較する
bool operator<(const State &state_1, const State &state_2)
{
    return state_1.evaluated_score_ < state_2.evaluated_score_;
}

// ビーム幅と制限時間(ms)を指定してビームサーチで行動を決定する
vector<pair<int,int>> beamSearchActionWithTimeThreshold(
    const State &state,
    const int beam_width,
    const int64_t time_threshold)
{
    auto time_keeper = TimeKeeper(time_threshold);
    auto legal_actions = state.legalActions();
    std::priority_queue<State> now_beam;
    State best_state;

    now_beam.push(state);
    for (int t = 0;; t++)
    {
        std::priority_queue<State> next_beam;
        for (int i = 0; i < beam_width; i++)
        {
            if (time_keeper.isTimeOver())
            {
                return best_state.actions_;
            }
            if (now_beam.empty())
                break;
            State now_state = now_beam.top();
            now_beam.pop();
            auto legal_actions = now_state.legalActions();
            for (const auto &action : legal_actions)
            {
                State next_state = now_state;
                next_state.advance(action);
                next_state.evaluateScore();
                
                next_state.actions_.emplace_back(action);
                next_beam.push(next_state);
            }
        }

        now_beam = next_beam;
        best_state = now_beam.top();

        if (best_state.isDone())
        {
            break;
        }
    }
    return best_state.actions_;
}

// 入力を読み取る
void read()
{
    // Step 1. 入力
	cin >> N;
	for (int i = 0; i < N; i++) cin >> A[i] >> B[i];
}

int main()
{
    /********************************************************************/
    // 1. 入力を読み取る
    read();
    /********************************************************************/

    State state{};
    state.cards_.resize(N);
    for (int i = 0; i < N; i++)
    {
        state.cards_[i].first = A[i];
        state.cards_[i].second = B[i];
    }

    auto actions = beamSearchActionWithTimeThreshold(state, 480, 975);

	cout << actions.size() << endl;
    for (auto &action : actions)
    {
        cout << action.first+1 << " " << action.second+1 << endl;
    }
    
    return 0;
}
0