結果
| 問題 | No.3418 【絶望】30個並列ごちゃ混ぜHit&Blowで遊ぼう! |
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2025-12-25 12:13:41 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.89.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 4,097 bytes |
| 記録 | |
| コンパイル時間 | 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 |
ソースコード
#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;
}