結果

問題 No.3418 【絶望】30個並列ごちゃ混ぜHit&Blowで遊ぼう!
コンテスト
ユーザー LNG
提出日時 2025-12-25 12:13:41
言語 C++17
(gcc 13.3.0 + boost 1.89.0)
結果
TLE  
実行時間 -
コード長 4,097 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 1,424 ms
コンパイル使用メモリ 126,528 KB
実行使用メモリ 42,140 KB
スコア 0
最終ジャッジ日時 2025-12-25 12:13:55
合計ジャッジ時間 14,278 ms
ジャッジサーバーID
(参考情報)
judge4 / judge3
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
other TLE * 1 -- * 99
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <random>
#include <chrono>

using namespace std;

struct Result {
    int h, b;
    bool operator<(const Result& other) const {
        if (h != other.h) return h < other.h;
        return b < other.b;
    }
    bool operator==(const Result& other) const {
        return h == other.h && b == other.b;
    }
};

Result get_hb(const string& q, const string& t) {
    int h = 0, common = 0;
    int mask_t = 0;
    for (char c : t) mask_t |= (1 << (c - '0'));
    for (int i = 0; i < 5; ++i) {
        if (q[i] == t[i]) h++;
        if (mask_t & (1 << (q[i] - '0'))) common++;
    }
    return {h, common - h};
}

bool is_valid(const string& s) {
    int mask = 0;
    for (char c : s) {
        int bit = 1 << (c - '0');
        if (mask & bit) return false;
        mask |= bit;
    }
    return true;
}

double calculate_entropy(const string& q, const vector<string>& candidates, int sample_size) {
    if (candidates.empty()) return 0;
    map<Result, int> counts;
    int n = candidates.size();
    int actual_sample = min(n, sample_size);
    
    static mt19937 rng(42);
    if (n <= sample_size) {
        for (const auto& c : candidates) counts[get_hb(q, c)]++;
    } else {
        for (int i = 0; i < actual_sample; ++i) {
            counts[get_hb(q, candidates[rng() % n])]++;
        }
    }

    double entropy = 0;
    for (auto const& [res, count] : counts) {
        double p = (double)count / actual_sample;
        entropy -= p * log2(p);
    }
    return entropy;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

    vector<string> all_possible;
    for (int i = 0; i <= 99999; i++) {
        string cur = to_string(i);
        while (cur.size() < 5) cur = "0" + cur;
        if (is_valid(cur)) all_possible.push_back(cur);
    }

    vector<string> candidates = all_possible;
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

    while (true) {
        string best_q;
        if (candidates.size() == all_possible.size()) {
            best_q = "01234";
        } else if (candidates.size() <= 30) {
            best_q = candidates[0];
        } else {
            double max_entropy = -1.0;
            for (int i = 0; i < 50; ++i) {
                string test_q = all_possible[rng() % all_possible.size()];
                double e = calculate_entropy(test_q, candidates, 300);
                if (e > max_entropy) {
                    max_entropy = e;
                    best_q = test_q;
                }
            }

            auto start_t = chrono::steady_clock::now();
            while (chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start_t).count() < 50) {
                string next_q = best_q;
                if (rng() % 2 == 0) {
                    swap(next_q[rng() % 5], next_q[rng() % 5]);
                } else {
                    int pos = rng() % 5;
                    char nv = '0' + (rng() % 10);
                    next_q[pos] = nv;
                }
                if (!is_valid(next_q)) continue;
                double e = calculate_entropy(next_q, candidates, 300);
                if (e > max_entropy) {
                    max_entropy = e;
                    best_q = next_q;
                }
            }
        }

        cout << best_q << "\n";
        fflush(stdout);

        vector<pair<int, int>> hb(30);
        map<Result, int> response_counts;
        for (int i = 0; i < 30; i++) {
            cin >> hb[i].first >> hb[i].second;
            response_counts[{hb[i].first, hb[i].second}]++;
        }

        if (hb[0].first == 5) break;

        vector<string> next_candidates;
        for (const auto& c : candidates) {
            Result r = get_hb(best_q, c);
            if (response_counts.count(r) && response_counts[r] > 0) {
                next_candidates.push_back(c);
            }
        }
        if (!next_candidates.empty()) {
            candidates = move(next_candidates);
        }
    }

    return 0;
}
0