結果
| 問題 |
No.5020 Averaging
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2024-02-25 15:47:05 |
| 言語 | C++17(gcc12) (gcc 12.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 3 ms / 1,000 ms |
| コード長 | 4,439 bytes |
| コンパイル時間 | 2,452 ms |
| コンパイル使用メモリ | 221,312 KB |
| 実行使用メモリ | 6,676 KB |
| スコア | 18,827,494 |
| 最終ジャッジ日時 | 2024-02-25 15:47:12 |
| 合計ジャッジ時間 | 4,147 ms |
|
ジャッジサーバーID (参考情報) |
judge13 / judge11 |
| 純コード判定しない問題か言語 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| other | AC * 50 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
using ull=unsigned long long;
std::mt19937 mt_for_action(0); // 行動選択用の乱数生成器を初期化
// 128bit整数
std::ostream &operator<<(std::ostream &dest, __int128_t value) {
std::ostream::sentry s(dest);
if (s) {
__uint128_t tmp = value < 0 ? -value : value;
char buffer[128];
char *d = std::end(buffer);
do {
--d;
*d = "0123456789"[tmp % 10];
tmp /= 10;
} while (tmp != 0);
if (value < 0) {
--d;
*d = '-';
}
int len = std::end(buffer) - d;
if (dest.rdbuf()->sputn(d, len) != len) {
dest.setstate(std::ios_base::badbit);
}
}
return dest;
}
__int128 parse(string &s) {
__int128 ret = 0;
for (int i = 0; i < s.length(); i++)
if ('0' <= s[i] && s[i] <= '9')
ret = 10 * ret + s[i] - '0';
return ret;
}
// 128bit整数ここまで
constexpr int MAX_TURN = 50;
constexpr __int128 TARGET = 500000000000000000;
struct Card {
__int128 omote, ura;
};
class GameState
{
private:
int _turn;
vector<Card> _cards;
vector<pair<int, int>> _commandHistory;
public:
double nowScore;
pair<int, int> first_action_;
GameState(){};
GameState(vector<unsigned long long> omotes, vector<unsigned long long> uras): _turn(0), nowScore(0) {
for (int i = 0; i < omotes.size(); i++) {
_cards.push_back({omotes[i], uras[i]});
}
}
double getEstimatedScore() {
ull v = max( max((ull)_cards[0].omote, (ull)TARGET) - min((ull)_cards[0].omote, (ull)TARGET), max((ull)_cards[0].ura, (ull)TARGET) - min((ull)_cards[0].ura, (ull)TARGET) );
return -1.0 * log10(static_cast<long double>(v));
}
// 1ターン進める
void advance(int u, int v)
{
_commandHistory.push_back({u, v});
_turn++;
Card newCard = {(_cards[u].omote + _cards[v].omote) / 2, (_cards[u].ura + _cards[v].ura) / 2};
_cards[u] = newCard;
_cards[v] = newCard;
nowScore = getEstimatedScore();
}
// 合法手を列挙する
vector<pair<int, int>> legalActions() const
{
vector<pair<int, int>> ret;
for (int i = 1; i < _cards.size(); i++) {
ret.push_back({0, i});
}
return ret;
}
// 1番目に触らないランダムなアクションを返す
pair<int, int> randomAction() const
{
uniform_int_distribution<int> dist(1, _cards.size());
int u = dist(mt_for_action);
int v = dist(mt_for_action);
while (u == v) {
v = dist(mt_for_action);
}
return {u, v};
}
// ゲームが終了しているかどうか
bool isDone() const
{
return _turn == MAX_TURN;
}
// 結果の出力を行う
string outputCommand() {
stringstream ss;
ss << _commandHistory.size() << endl;
for (auto command : _commandHistory) {
ss << command.first + 1 << " " << command.second + 1 << endl;
}
return ss.str();
}
// 現在の実スコアを出力する
double getScore() {
ull v = max( max((ull)_cards[0].omote, (ull)TARGET) - min((ull)_cards[0].omote, (ull)TARGET), max((ull)_cards[0].ura, (ull)TARGET) - min((ull)_cards[0].ura, (ull)TARGET) );
long long score = 2000000 - 100000 * log10(static_cast<long double>(v));
return score;
}
};
bool operator<(const GameState &state1, const GameState &state2)
{
return state1.nowScore < state2.nowScore;
}
GameState greedyAction(const GameState &nowState) {
GameState nextState = nowState;
auto legal_actions = nowState.legalActions();
double maxScore = -1e30;
for (const auto &action : legal_actions) {
GameState nextStateTmp = nowState;
nextStateTmp.advance(action.first, action.second);
if (nextStateTmp.nowScore > maxScore) {
maxScore = nextStateTmp.nowScore;
nextState = nextStateTmp;
}
}
if (nowState.nowScore > maxScore) {
nextState = nowState;
auto random_action = nowState.randomAction();
nextState.advance(random_action.first, random_action.second);
}
return nextState;
}
pair<vector<ull>, vector<ull>> getFromInput() {
int n;
cin >> n;
vector<ull> omotes(n), uras(n);
for (int i = 0; i < n; i++) {
cin >> omotes[i] >> uras[i];
}
return {omotes, uras};
}
int main(){
auto input = getFromInput();
GameState state(input.first, input.second);
while (!state.isDone()) {
state = greedyAction(state);
// cerr<<state.nowScore<<endl;
}
cout << state.outputCommand();
// cerr << state.getScore() << endl;
return 0;
}