提出 #67393389


ソースコード 拡げる

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

// 1-Step Simulator: 管理用クラス
class StepSimulator {
public:
    int N;
    int dr[4] = {-1,1,0,0};
    int dc[4] = {0,0,-1,1};

    StepSimulator(int N_) : N(N_) {}

    struct State {
        vector<vector<double>> prob;      // 現在の期待値分布
        vector<vector<bool>> occ;         // 岩配置マップ
    };
    struct Result {
        vector<vector<double>> next_prob;
        vector<vector<bool>> next_occ;
    };

    // 1ステップ実行
    // 入力: current State + place (配置位置)
    // 出力: 更新後の分布とマップ
    Result step(const State &s, pair<int,int> place) {
        auto &prob = s.prob;
        auto &occ = s.occ;
        vector<vector<double>> next_prob(N, vector<double>(N, 0.0));
        vector<vector<bool>> next_occ = occ;

        // 分配: 各セルから4方向に等確率でスライド
        for(int i = 0; i < N; ++i) {
            for(int j = 0; j < N; ++j) {
                if (occ[i][j]) continue;
                double p = prob[i][j];
                if (p <= 0.0) continue;
                // 各方向に確率 p/4 ずつ分配
                for(int d = 0; d < 4; ++d) {
                    int ni = i, nj = j;
                    // 岩に当たるまでスライド
                    while (true) {
                        int ti = ni + dr[d], tj = nj + dc[d];
                        if (ti < 0 || ti >= N || tj < 0 || tj >= N || occ[ti][tj]) break;
                        ni = ti; nj = tj;
                    }
                    next_prob[ni][nj] += p * 0.25;
                }
            }
        }
        // 配置位置を岩に
        int bi = place.first;
        int bj = place.second;
        next_occ[bi][bj] = true;
        // そのセルの確率消去
        next_prob[bi][bj] = 0.0;

        return {next_prob, next_occ};
    }
};

// AHC050: Monte Carlo + expectation scoring
struct Cell { int r,c; };
int N = 40, M;
vector<string> grid;
vector<Cell> empties;
int T;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());

// compute_expected_sum: Pに従ってStepSimulatorで1ステップずつ更新し、ステップごとの総期待値を加算
double compute_expected_sum(const vector<int>& P) {
    // 初期State
    vector<vector<double>> prob(N, vector<double>(N, 0.0));
    vector<vector<bool>> occ(N, vector<bool>(N, false));
    double init_p = 1.0 / T;
    for (auto &c : empties) prob[c.r][c.c] = init_p;
    for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j)
            if (grid[i][j] == '#') occ[i][j] = true;

    StepSimulator sim(N);
    StepSimulator::State state{prob, occ};

    double E_sum = 0.0;
    // 各ステップ
    for (int idx : P) {
        // 1-step
        auto res = sim.step(state, {empties[idx].r, empties[idx].c});
        // スコア加算: next_probの全空きセル期待値
        for (auto &c : empties) {
            if (!state.occ[c.r][c.c]) E_sum += res.next_prob[c.r][c.c];
        }
        // State更新
        state.prob = move(res.next_prob);
        state.occ  = move(res.next_occ);
    }
    return E_sum;
}

// スコア計算: round(E_sum * 1e6 / (T-1))
int compute_score(double E) {
    return (int)llround(E * 1e6 / (T - 1));
}

int simulate_one(const vector<int>& P) {
    uniform_int_distribution<int> dist(0, T-1);
    int cur_r = empties[dist(rng)].r;
    int cur_c = empties[dist(rng)].c;
    vector<vector<bool>> occ(N, vector<bool>(N, false));
    for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j)
            if (grid[i][j] == '#') occ[i][j] = true;
    int steps = 0;
    for (int idx : P) {
        int dir = rng() % 4;
        static int dr[4] = {-1,1,0,0};
        static int dc[4] = {0,0,-1,1};
        int nr = cur_r, nc = cur_c;
        // スライド移動
        while (true) {
            int ti = nr + dr[dir], tj = nc + dc[dir];
            if (ti < 0 || ti >= N || tj < 0 || tj >= N || occ[ti][tj]) break;
            nr = ti; nc = tj;
        }
        cur_r = nr; cur_c = nc;
        int br = empties[idx].r, bc = empties[idx].c;
        if (cur_r == br && cur_c == bc) break;
        occ[br][bc] = true;
        steps++;
    }
    return steps;
}

double estimate(const vector<int>& P, int K) {
    ll s = 0;
    while (K--) s += simulate_one(P);
    return (double)s / K;
}

// Greedy 解法: 各ステップで最もロボット存在確率が小さいセルに岩を配置
// 入力: 初期 State, StepSimulator
// 出力: 貪欲に選んだ配置順序 P (empties のインデックス)
vector<int> greedy_sequence(const StepSimulator::State &init_state, StepSimulator &sim) {
    StepSimulator::State state = init_state;
    // empties のセル位置からインデックスを引くマップ
    unordered_map<long long,int> empty_idx;
    for (int k = 0; k < (int)empties.size(); ++k) {
        long long key = ((long long)empties[k].r << 32) | (unsigned)empties[k].c;
        empty_idx[key] = k;
    }

    vector<int> P;
    P.reserve(empties.size());

    // 各ステップで
    for (size_t step = 0; step < empties.size(); ++step) {
        // 最小確率セルを探索
        double best_p = numeric_limits<double>::infinity();
        pair<int,int> best_cell = {-1,-1};
        for (auto &c : empties) {
            int i = c.r, j = c.c;
            if (state.occ[i][j]) continue;
            if (state.prob[i][j] < best_p) {
                best_p = state.prob[i][j];
                best_cell = {i, j};
            }
        }
        if (best_cell.first < 0) break;
        // インデックスを取得して順序に追加
        long long key = ((long long)best_cell.first << 32) | (unsigned)best_cell.second;
        P.push_back(empty_idx[key]);

        // 1ステップ更新
        auto res = sim.step(state, best_cell);
        state.prob = move(res.next_prob);
        state.occ  = move(res.next_occ);
    }
    return P;
}
// Beam Search 解法: 各ステップでトップ A 候補を展開し、スコア上位 B プリフィックスを保持
// 入力:
//   init_state: 初期の期待値分布と岩配置マップ
//   sim: StepSimulator インスタンス
//   A: 各プリフィックスから展開する候補数
//   B: 次ステップに残すビーム幅
// 出力:
//   最終的に選んだ配置順序 P (empties のインデックス)

// Beam Search: depth (= 残りステップ数) だけ探索する5引数版
vector<int> beam_search(const StepSimulator::State &init_state,
                        StepSimulator &sim,
                        int A, int B,
                        int depth) {
    struct Node {
        StepSimulator::State state;
        vector<int> P;
        double score;
    };
    int full_T = empties.size();
    // (r,c) → empties インデックス
    unordered_map<long long,int> empty_idx;
    empty_idx.reserve(full_T);
    for (int k = 0; k < full_T; ++k) {
        long long key = ((long long)empties[k].r << 32) | (unsigned)empties[k].c;
        empty_idx[key] = k;
    }

    // 初期ビーム
    vector<Node> beam;      beam.reserve(B);
    vector<Node> next_beam; next_beam.reserve(B * A);

    beam.push_back(Node{init_state, {}, 0.0});
    beam[0].P.reserve(depth);

    // depth ステップだけ回す
    for (int t = 0; t < depth; ++t) {
        next_beam.clear();
        for (auto &node : beam) {
            // 未配置セルから確率が小さい順に上位A件をピック
            vector<pair<double,pair<int,int>>> cand;
            cand.reserve(full_T);
            for (auto &c : empties) {
                if (!node.state.occ[c.r][c.c])
                    cand.emplace_back(node.state.prob[c.r][c.c], make_pair(c.r,c.c));
            }
            nth_element(cand.begin(),
                        cand.begin() + min(A,(int)cand.size()),
                        cand.end(),
                        [](auto &a, auto &b){ return a.first < b.first; });
            cand.resize(min(A,(int)cand.size()));

            // 各候補で展開
            for (auto &kv : cand) {
                auto cell = kv.second;
                auto res = sim.step(node.state, cell);
                // delta = next_prob の合計
                double delta = 0;
                for (auto &e : empties) {
                    if (!node.state.occ[e.r][e.c])
                        delta += res.next_prob[e.r][e.c];
                }
                Node nn;
                nn.state.prob = move(res.next_prob);
                nn.state.occ  = move(res.next_occ);
                nn.P = node.P;
                nn.P.reserve(node.P.size()+1);
                long long key = ((long long)cell.first<<32)|(unsigned)cell.second;
                nn.P.push_back(empty_idx[key]);
                nn.score = node.score + delta;
                next_beam.push_back(move(nn));
            }
        }
        // スコア降順で B 件に切り詰め
        sort(next_beam.begin(), next_beam.end(),
             [](auto &a, auto &b){ return a.score > b.score; });
        if ((int)next_beam.size() > B)
            next_beam.resize(B);
        beam.swap(next_beam);
    }

    // 最終ビーム内で最良ノードを選択
    auto best = max_element(beam.begin(), beam.end(),
                            [](auto &a, auto &b){ return a.score < b.score; });
    return best->P;
}

// next_greedy_step: 現在の State から 1ステップ分貪欲に配置セルを選ぶ
// 確率が同じ場合は、中心に近いセルを優先
int next_greedy_step_mid(const StepSimulator::State &state,
                     const vector<Cell> &empties,
                     const unordered_map<long long,int> &idx_map) {
    const double eps = 1e-12;
    double best_p = numeric_limits<double>::infinity();
    double best_dist = numeric_limits<double>::infinity();
    pair<int,int> best_cell{-1,-1};
    // グリッド中心
    double ci = (state.prob.size() - 1) / 2.0;
    double cj = (state.prob[0].size() - 1) / 2.0;

    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        double p = state.prob[i][j];
        // マンハッタン距離 or ユークリッド距離
        double dist = abs(i - ci) + abs(j - cj);

        if (p + eps < best_p ||
           (abs(p - best_p) < eps && dist < best_dist)) {
            best_p    = p;
            best_dist = dist;
            best_cell = {i, j};
        }
    }
    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}
// next_greedy_step: 現在の State から 1ステップ分貪欲に配置セルを選ぶ
// 入力: state, empties, idx_map
// 出力: 選んだ empties のインデックス
int next_greedy_step(const StepSimulator::State &state,
                     const vector<Cell> &empties,
                     const unordered_map<long long,int> &idx_map) {
    double best_p = numeric_limits<double>::infinity();
    pair<int,int> best_cell{-1,-1};
    for (auto &c : empties) {
        if (state.occ[c.r][c.c]) continue;
        if (state.prob[c.r][c.c] < best_p) {
            best_p = state.prob[c.r][c.c];
            best_cell = {c.r, c.c};
        }
    }
    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}
// next_greedy_step_outside: 確率が同じなら中心から遠いセルを優先して外側から埋める
int next_greedy_step_outside(const StepSimulator::State &state,
                             const vector<Cell> &empties,
                             const unordered_map<long long,int> &idx_map) {
    const double eps = 1e-12;
    double best_p = numeric_limits<double>::infinity();
    double best_dist = -1.0;                // ← 最遠を探すので初期値は小さく
    pair<int,int> best_cell{-1,-1};
    double ci = (state.prob.size() - 1) / 2.0;
    double cj = (state.prob[0].size() - 1) / 2.0;

    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        double p = state.prob[i][j];
        double dist = abs(i - ci) + abs(j - cj);  // 中心からのマンハッタン距離

        if (p + eps < best_p ||
           (abs(p - best_p) < eps && dist > best_dist)) {
            best_p    = p;
            best_dist = dist;
            best_cell = {i, j};
        }
    }
    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}

// next_greedy_step_complex:
//  1) 最小のロボット存在確率 p(i,j) を第一基準に選ぶ
//  2) 同率の場合は、上下左右で「すでに岩が置かれたセル」の数を最も多く持つセルを優先
//  3) さらに同率の場合は、中心からの距離が小さい(中心寄り)セルを優先
int next_greedy_step_complex(
    const StepSimulator::State &state,
    const vector<Cell>           &empties,
    const unordered_map<long long,int> &idx_map)
{
    const double eps = 1e-12;
    double best_p    = numeric_limits<double>::infinity();
    int    best_adj  = -1;
    double best_dist = numeric_limits<double>::infinity();
    pair<int,int> best_cell{-1,-1};

    // グリッド中心
    double ci = (state.prob.size() - 1) / 2.0;
    double cj = (state.prob[0].size() - 1) / 2.0;

    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        double p = state.prob[i][j];

        // 1) 第一基準: 確率 p(i,j)
        if (p > best_p + eps) continue;

        // 2) 隣接済みブロック数を数える
        int adj = 0;
        static int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};
        for (int d = 0; d < 4; ++d) {
            int ni = i + dr[d], nj = j + dc[d];
            if (ni >= 0 && ni < state.occ.size()
             && nj >= 0 && nj < state.occ.size()
             && state.occ[ni][nj]) {
                ++adj;
            }
        }

        // 3) 中心からの距離
        double dist = fabs(i - ci) + fabs(j - cj);

        // 比較: (p, -adj, dist) の三段比較
        bool better = false;
        if (p + eps < best_p) {
            better = true;
        } else if (fabs(p - best_p) < eps) {
            if (adj > best_adj) {
                better = true;
            } else if (adj == best_adj) {
                if (dist < best_dist - eps) {
                    better = true;
                }
            }
        }
        if (better) {
            best_p    = p;
            best_adj  = adj;
            best_dist = dist;
            best_cell = {i,j};
        }
    }

    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}
// next_greedy_step_center_first:
//  1) 中心からの距離を第一優先で最小にするセルを選ぶ
//  2) 同距離の場合は、ロボット存在確率 p(i,j) が小さいセルを優先
//  3) さらに同率の場合は、上下左右の既設ブロック隣接数が多いセルを優先
int next_greedy_step_center_first(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map)
{
    const double eps = 1e-12;
    double best_dist = numeric_limits<double>::infinity();
    double best_p    = numeric_limits<double>::infinity();
    int    best_adj  = -1;
    pair<int,int> best_cell{-1,-1};

    // グリッド中心
    double ci = (state.prob.size() - 1) / 2.0;
    double cj = (state.prob[0].size() - 1) / 2.0;

    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;

        // 1) 中心からのマンハッタン距離
        double dist = fabs(i - ci) + fabs(j - cj);
        if (dist > best_dist + eps) continue;

        // 2) ロボット存在確率
        double p = state.prob[i][j];

        // 3) 隣接ブロック数
        int adj = 0;
        static int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};
        for (int d = 0; d < 4; ++d) {
            int ni = i + dr[d], nj = j + dc[d];
            if (ni >= 0 && ni < state.occ.size()
             && nj >= 0 && nj < state.occ.size()
             && state.occ[ni][nj]) {
                ++adj;
            }
        }

        bool better = false;
        if (dist + eps < best_dist) {
            better = true;
        } else if (fabs(dist - best_dist) < eps) {
            if (p + eps < best_p) {
                better = true;
            } else if (fabs(p - best_p) < eps) {
                if (adj > best_adj) {
                    better = true;
                }
            }
        }

        if (better) {
            best_dist = dist;
            best_p    = p;
            best_adj  = adj;
            best_cell = {i, j};
        }
    }

    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}

// next_greedy_step_custom_outside:
//  1) ロボット存在確率 p(i,j) が最小のセルを選ぶ
//  2) p が同じ場合は、中心からのマンハッタン距離が大きい(外側の)セルを優先
//  3) それも同じ場合は、上下左右に隣接する既設ブロック数が多いセルを優先
int next_greedy_step_custom_outside(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map)
{
    const double eps = 1e-12;
    double best_p    = numeric_limits<double>::infinity();
    double best_dist = -1.0;  // 外側優先なので初期は小さく
    int    best_adj  = -1;
    pair<int,int> best_cell{-1,-1};

    // グリッド中心座標
    double ci = (state.prob.size()-1) * 0.5;
    double cj = (state.prob[0].size()-1) * 0.5;

    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;

        double p = state.prob[i][j];
        // 1) 確率で比較
        if (p > best_p + eps) continue;

        // 2) 中心からのマンハッタン距離(外側優先)
        double dist = fabs(i - ci) + fabs(j - cj);

        // 3) 隣接ブロック数
        int adj = 0;
        static int dr[4]={-1,1,0,0}, dc[4]={0,0,-1,1};
        for (int d=0; d<4; ++d) {
            int ni=i+dr[d], nj=j+dc[d];
            if (ni>=0 && ni<state.occ.size() &&
                nj>=0 && nj<state.occ.size() &&
                state.occ[ni][nj]) {
                ++adj;
            }
        }

        bool better = false;
        if (p + eps < best_p) {
            better = true;
        }
        else if (fabs(p - best_p) < eps) {
            if (dist > best_dist + eps) {
                better = true;
            }
            else if (fabs(dist - best_dist) < eps) {
                if (adj > best_adj) {
                    better = true;
                }
            }
        }

        if (better) {
            best_p    = p;
            best_dist = dist;
            best_adj  = adj;
            best_cell = {i,j};
        }
    }

    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}

// stepSimulator や next_greedy_step_custom_outside / _inside は既に定義済みとします。
// next_greedy_step_custom_inside:
//  1) ロボット存在確率 p(i,j) が最小のセルを選ぶ
//  2) p が同じ場合は、中心からのマンハッタン距離が小さい(内側の)セルを優先
//  3) さらに同じ場合は、上下左右に隣接する既設ブロック数が多いセルを優先
int next_greedy_step_custom_inside(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map)
{
    const double eps = 1e-12;
    double best_p    = numeric_limits<double>::infinity();
    double best_dist = numeric_limits<double>::infinity();
    int    best_adj  = -1;
    pair<int,int> best_cell{-1,-1};

    // グリッド中心座標
    double ci = (state.prob.size() - 1) * 0.5;
    double cj = (state.prob[0].size() - 1) * 0.5;

    static int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};

    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;

        double p = state.prob[i][j];
        // 1) 確率で比較
        if (p > best_p + eps) continue;

        // 2) 中心からのマンハッタン距離(内側優先)
        double dist = fabs(i - ci) + fabs(j - cj);

        // 3) 隣接ブロック数
        int adj = 0;
        for (int d = 0; d < 4; ++d) {
            int ni = i + dr[d], nj = j + dc[d];
            if (ni >= 0 && ni < state.occ.size() &&
                nj >= 0 && nj < state.occ.size() &&
                state.occ[ni][nj]) {
                ++adj;
            }
        }

        // 総合比較
        bool better = false;
        if (p + eps < best_p) {
            better = true;
        }
        else if (fabs(p - best_p) < eps) {
            if (dist + eps < best_dist) {
                better = true;
            }
            else if (fabs(dist - best_dist) < eps) {
                if (adj > best_adj) {
                    better = true;
                }
            }
        }

        if (better) {
            best_p    = p;
            best_dist = dist;
            best_adj  = adj;
            best_cell = {i, j};
        }
    }

    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}
// 1…100: 外側優先
// 101…: 10stepごとに inside/outside を切り替え
vector<int> greedy_ring_switch(const StepSimulator::State &init_state,
                               StepSimulator &sim) {
    StepSimulator::State state = init_state;
    vector<int> P;
    P.reserve(T);

    // idx_map 準備
    unordered_map<long long,int> idx_map;
    idx_map.reserve(T);
    for(int k=0;k<T;k++){
        long long key = ((long long)empties[k].r<<32)|(unsigned)empties[k].c;
        idx_map[key] = k;
    }

    for(int t = 0; t < T; ++t) {
        // どちらの戦略を使うか決定
        bool use_outside;
        if (t < 1000) {
            use_outside = true;
        } else {
            int phase = ((t - 100) / 1) % 2;
            use_outside = (phase == 0);  // even → outside, odd → inside
        }

        // 次に配置するセルを選択
        int idx;
        if (use_outside) {
            idx = next_greedy_step_custom_outside(state, empties, idx_map);
        } else {
            idx = next_greedy_step_custom_inside(state, empties, idx_map);
        }

        // 配置
        P.push_back(idx);
        auto cell = empties[idx];
        auto res  = sim.step(state, {cell.r, cell.c});
        state.prob = move(res.next_prob);
        state.occ  = move(res.next_occ);
    }
    return P;
}

// 置いた後の分布の分散(二次モーメント)を計算するヘルパー
double compute_variance(const vector<vector<double>>& prob) {
    // グリッド中心 (ci,cj)
    double ci = (N-1)*0.5, cj = (N-1)*0.5;
    // 期待値(重心)が ci,cj なので分散は E[(x-ci)^2+(y-cj)^2]
    double var = 0;
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            double p = prob[i][j];
            if(p <= 0) continue;
            double di = i - ci;
            double dj = j - cj;
            var += p * (di*di + dj*dj);
        }
    }
    return var;
}

// next_greedy_step_by_variance:
//  1) p(i,j) が同じなら考慮せずにすべての空セルを候補に
//  2) 各候補 v を置いた場合の next_prob を sim.step で得て
//     compute_variance(next_prob) を計算
//  3) その分散 var_v が最大となる v を選択
int next_greedy_step_by_variance(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map,
    StepSimulator              &sim
) {
    int best_idx = -1;
    double best_var = -1;
    // 各空きセルを試し置き
    for(auto &c : empties) {
        int i = c.r, j = c.c;
        if(state.occ[i][j]) continue;

        // 1ステップシミュレーション
        auto res = sim.step(state, {i,j});
        // 分散を計算
        double var = compute_variance(res.next_prob);

        // より大きい分散を優先
        if (var > best_var) {
            best_var = var;
            long long key = ((long long)i<<32)|(unsigned)j;
            best_idx = idx_map.at(key);
        }
    }
    return best_idx;
}

// 1) 分布のエントロピーを計算するヘルパー
double compute_entropy(const vector<vector<double>>& prob) {
    double H = 0;
    for(int i = 0; i < N; ++i) {
        for(int j = 0; j < N; ++j) {
            double p = prob[i][j];
            if (p > 0) {
                H -= p * log(p);
            }
        }
    }
    return H;
}

// 2) next step をエントロピー減少量で選ぶ関数
int next_greedy_step_by_entropy(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map,
    StepSimulator              &sim
) {
    double H0 = compute_entropy(state.prob);

    int best_idx = -1;
    double best_delta = -1;
    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;

        // 1ステップ後の分布を得る
        auto res = sim.step(state, {i,j});

        // エントロピーを計算
        double H1 = compute_entropy(res.next_prob);

        // 減少量 ΔH = H0 - H1 を最大化
        double delta = H0 - H1;
        if (delta > best_delta) {
            best_delta = delta;
            long long key = ((long long)i << 32) | (unsigned)j;
            best_idx = idx_map.at(key);
        }
    }
    return best_idx;
}

// 外側偏重:p/(dist+eps) を最小化
int next_greedy_step_ratio_outside(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map
) {
    const double eps = 1e-6;
    double best_score = numeric_limits<double>::infinity();
    int    best_adj   = -1;
    pair<int,int> best_cell{-1,-1};

    double ci = (state.prob.size()-1)*0.5;
    double cj = (state.prob[0].size()-1)*0.5;

    static int dr[4]={-1,1,0,0}, dc[4]={0,0,-1,1};

    for(auto &c : empties){
        int i = c.r, j = c.c;
        if(state.occ[i][j]) continue;

        double p = state.prob[i][j];
        double dist = fabs(i - ci) + fabs(j - cj);
        double score = p / (dist + eps);

        // 隣接岩数
        int adj = 0;
        for(int d=0; d<4; d++){
            int ni = i + dr[d], nj = j + dc[d];
            if(ni>=0 && ni<state.occ.size() &&
               nj>=0 && nj<state.occ.size() &&
               state.occ[ni][nj]) {
              ++adj;
            }
        }

        bool better = false;
        if(score < best_score){
            better = true;
        } else if(fabs(score - best_score) < 1e-12 && adj > best_adj){
            better = true;
        }

        if(better){
            best_score = score;
            best_adj   = adj;
            best_cell  = {i,j};
        }
    }

    long long key = ((long long)best_cell.first<<32)|(unsigned)best_cell.second;
    return idx_map.at(key);
}

// 必要なユーティリティ:スライド先テーブルの構築
vector<array<int,4>> build_slide_to(const vector<vector<bool>>& occ){
    vector<array<int,4>> slide_to(N*N);
    static int dr[4]={-1,1,0,0}, dc[4]={0,0,-1,1};
    for(int i=0;i<N;i++){
        for(int j=0;j<N;j++){
            int u = i*N + j;
            if(occ[i][j]){
                slide_to[u] = {u,u,u,u};
                continue;
            }
            for(int d=0;d<4;d++){
                int ni=i, nj=j;
                while(true){
                    int ti = ni+dr[d], tj = nj+dc[d];
                    if(ti<0||ti>=N||tj<0||tj>=N||occ[ti][tj]) break;
                    ni=ti; nj=tj;
                }
                slide_to[u][d] = ni*N + nj;
            }
        }
    }
    return slide_to;
}

// 拡張版:複数指標(p, dist, adj, flow, grad)で候補を選ぶ
int next_greedy_step_enhanced(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map,
    StepSimulator              &sim
) {
    // 1) スライド先 & flow の事前計算
    auto slide_to = build_slide_to(state.occ);
    vector<ll> flow(N*N, 0);
    for(int u=0; u<N*N; ++u){
        int ui=u/N, uj=u%N;
        if(state.occ[ui][uj]) continue;
        for(int d=0; d<4; ++d){
            int v = slide_to[u][d];
            if(!state.occ[v/N][v%N]) flow[v]++;
        }
    }

    // 2) grad(確率勾配)の計算
    vector<double> grad(N*N, 0.0);
    static int dr[4]={-1,1,0,0}, dc[4]={0,0,-1,1};
    for(auto &c : empties){
        int i=c.r, j=c.c;
        if(state.occ[i][j]) continue;
        double g=0;
        double p = state.prob[i][j];
        for(int d=0;d<4;d++){
            int ni=i+dr[d], nj=j+dc[d];
            if(ni<0||ni>=N||nj<0||nj>=N||state.occ[ni][nj]) continue;
            g += fabs(p - state.prob[ni][nj]);
        }
        grad[i*N+j] = g;
    }

    // 3) 候補選定:lex 比較
    const double eps = 1e-12;
    double ci = (N-1)*0.5, cj = (N-1)*0.5;

    double best_p    = numeric_limits<double>::infinity();
    double best_dist = -1.0;
    int    best_adj  = -1;
    ll     best_flow = -1;
    double best_grad = -1.0;
    pair<int,int> best_cell{-1,-1};

    for(auto &c : empties){
        int i=c.r, j=c.c;
        if(state.occ[i][j]) continue;
        double p = state.prob[i][j];
        if(p > best_p + eps) continue;

        double dist = fabs(i - ci) + fabs(j - cj);
        int adj = 0;
        for(int d=0;d<4;d++){
            int ni=i+dr[d], nj=j+dc[d];
            if(ni>=0&&ni<N&&nj>=0&&nj<N&&state.occ[ni][nj]) adj++;
        }
        ll f = flow[i*N+j];
        double g = grad[i*N+j];

        bool better = false;
        if (p + eps < best_p) {
            better = true;
        } else if (fabs(p - best_p) < eps) {
            if (dist > best_dist + eps) {
                better = true;
            } else if (fabs(dist - best_dist) < eps) {
                if (adj > best_adj) {
                    better = true;
                } else if (adj == best_adj) {
                    if (f > best_flow) {
                        better = true;
                    } else if (f == best_flow) {
                        if (g > best_grad + eps) {
                            better = true;
                        }
                    }
                }
            }
        }

        if (better) {
            best_p    = p;
            best_dist = dist;
            best_adj  = adj;
            best_flow = f;
            best_grad = g;
            best_cell = {i,j};
        }
    }

    long long key = ((long long)best_cell.first<<32)|(unsigned)best_cell.second;
    return idx_map.at(key);
}
int next_greedy_step_adjprob(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map
) {
    const double eps = 1e-12;
    // STEP1: 最小 p を見つける
    double best_p = numeric_limits<double>::infinity();
    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        best_p = min(best_p, state.prob[i][j]);
    }

    // STEP2: 最小 p のセルの中で、
    //  - まず「隣接確率和 adj_sum」を最大化、
    //  - さらに adj_sum が同じなら「隣接最大値 adj_max」を最大化
    static int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};
    double best_adj_sum = -1.0;
    double best_adj_max = -1.0;
    pair<int,int> best_cell{-1,-1};

    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        double p = state.prob[i][j];
        if (fabs(p - best_p) > eps) continue;

        // 隣接和と隣接最大値を計算
        double adj_sum = 0.0, adj_max = 0.0;
        for (int d = 0; d < 4; ++d) {
            int ni = i + dr[d], nj = j + dc[d];
            if (ni >= 0 && ni < N && nj >= 0 && nj < N && !state.occ[ni][nj]) {
                double q = state.prob[ni][nj];
                adj_sum += q;
                adj_max = max(adj_max, q);
            }
        }

        // 比較:まず adj_sum、同値なら adj_max
        if (adj_sum > best_adj_sum + eps ||
           (fabs(adj_sum - best_adj_sum) < eps && adj_max > best_adj_max + eps)) {
            best_adj_sum = adj_sum;
            best_adj_max = adj_max;
            best_cell = {i, j};
        }
    }

    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}

// 1) p(i,j) が最小のセルを絞り込み  
// 2) その中で、上下左右4近傍の最大確率 adj_max を最大化  
// 3) それでも並んだら、中心からのマンハッタン距離 dist を最大化(外側優先)  
int next_greedy_step_adjmax_outside(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map
) {
    const double eps = 1e-12;
    // STEP1: 最小 p を求める
    double min_p = numeric_limits<double>::infinity();
    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        min_p = min(min_p, state.prob[i][j]);
    }

    // グリッド中心
    double ci = (N - 1) * 0.5;
    double cj = (N - 1) * 0.5;
    static int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};

    double best_adj_max = -1.0;
    double best_dist    = -1.0;
    pair<int,int> best_cell{-1,-1};

    // STEP2 & 3: min_pセルの中で adj_max→dist の順で選ぶ
    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        double p = state.prob[i][j];
        if (fabs(p - min_p) > eps) continue;

        // 隣接最大値を計算
        double local_max = 0;
        for (int d = 0; d < 4; ++d) {
            int ni = i + dr[d], nj = j + dc[d];
            if (ni >= 0 && ni < N && nj >= 0 && nj < N && !state.occ[ni][nj]) {
                local_max = max(local_max, state.prob[ni][nj]);
            }
        }
        // 中心からのマンハッタン距離
        double dist = fabs(i - ci) + fabs(j - cj);

        // 比較: adj_max ↑, dist ↑
        if (local_max > best_adj_max + eps ||
           (fabs(local_max - best_adj_max) < eps && dist > best_dist + eps)) {
            best_adj_max = local_max;
            best_dist    = dist;
            best_cell    = {i, j};
        }
    }

    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}

// 1) p(i,j) が最小のセルを絞り込み  
// 2) その中で、上下左右4近傍の最大確率 adj_max を最大化  
// 3) それでも並んだら、中心からのマンハッタン距離 dist を最小化(内側優先)  
int next_greedy_step_adjmax_inside(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map
) {
    const double eps = 1e-12;
    // STEP1: 最小 p を求める
    double min_p = numeric_limits<double>::infinity();
    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        min_p = min(min_p, state.prob[i][j]);
    }

    // グリッド中心
    double ci = (N - 1) * 0.5;
    double cj = (N - 1) * 0.5;
    static int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};

    double best_adj_max = -1.0;
    double best_dist    = numeric_limits<double>::infinity();
    pair<int,int> best_cell{-1,-1};

    // STEP2 & 3: min_pセルの中で adj_max→dist(inward) の順で選ぶ
    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        double p = state.prob[i][j];
        if (fabs(p - min_p) > eps) continue;

        // 隣接最大値を計算
        double local_max = 0;
        for (int d = 0; d < 4; ++d) {
            int ni = i + dr[d], nj = j + dc[d];
            if (ni >= 0 && ni < N && nj >= 0 && nj < N && !state.occ[ni][nj]) {
                local_max = max(local_max, state.prob[ni][nj]);
            }
        }
        // 中心からのマンハッタン距離
        double dist = fabs(i - ci) + fabs(j - cj);

        // 比較: adj_max ↑, dist ↓
        if (local_max > best_adj_max + eps ||
           (fabs(local_max - best_adj_max) < eps && dist + eps < best_dist)) {
            best_adj_max = local_max;
            best_dist    = dist;
            best_cell    = {i, j};
        }
    }

    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}
// 1) p(i,j) が最小のセルを絞り込み  
// 2) その中で、上下左右4近傍の最大確率 adj_max を最大化  
// 3) それでも並んだら、
//    置いたあとにその adj_max セルの「最大スライド距離」が  
//    どれだけ減るか(減少量)を最大化
// 1) p(i,j) が最小のセルを絞り込み  
// 2) その中で、上下左右4近傍の最大確率 adj_max を最大化  
// 3) 置いたときにその adj_max セルの「最大スライド距離」が最も減るセルを選ぶ
int next_greedy_step_adjmax_trap(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map
) {
    const double eps = 1e-12;
    int N = state.prob.size();
    static int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};

    // STEP1: 最小 p を求める
    double min_p = numeric_limits<double>::infinity();
    for (auto &c : empties) if (!state.occ[c.r][c.c])
        min_p = min(min_p, state.prob[c.r][c.c]);

    // STEP2: min_p セルの中で隣接最大 prob を求め候補リストに
    double best_adj_max = -1.0;
    vector<Cell> cand;
    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j] || fabs(state.prob[i][j] - min_p) > eps) continue;
        double local_max = 0;
        for (int d=0; d<4; ++d) {
            int ni=i+dr[d], nj=j+dc[d];
            if (ni>=0&&ni<N&&nj>=0&&nj<N&&!state.occ[ni][nj])
                local_max = max(local_max, state.prob[ni][nj]);
        }
        if (local_max > best_adj_max + eps) {
            best_adj_max = local_max;
            cand.clear();
            cand.push_back(c);
        } else if (fabs(local_max - best_adj_max) < eps) {
            cand.push_back(c);
        }
    }

    // STEP3: それらをトラップ効果で選別
    auto slide_len = [&](int si, int sj, const vector<vector<bool>>& occ_map){
        int maxd=0;
        for(int d=0;d<4;d++){
            int dist=0, ni=si, nj=sj;
            while(true){
                int ti=ni+dr[d], tj=nj+dc[d];
                if(ti<0||ti>=N||tj<0||tj>=N||occ_map[ti][tj]) break;
                ni=ti; nj=tj; ++dist;
            }
            maxd = max(maxd, dist);
        }
        return maxd;
    };

    double best_reduction = -1.0;
    pair<int,int> best_cell{-1,-1};

    for (auto &c : cand) {
        int i=c.r, j=c.c;
        // adj_max セルを同様に見つける
        double local_max=0; pair<int,int> target{-1,-1};
        for(int d=0;d<4;d++){
            int ni=i+dr[d], nj=j+dc[d];
            if(ni>=0&&ni<N&&nj>=0&&nj<N&&!state.occ[ni][nj]){
                double q = state.prob[ni][nj];
                if (q > local_max + eps) {
                    local_max = q;
                    target = {ni,nj};
                }
            }
        }
        if (target.first<0) continue;
        double orig = slide_len(target.first, target.second, state.occ);
        auto occ2 = state.occ;
        occ2[i][j] = true;
        double now  = slide_len(target.first, target.second, occ2);
        double red  = orig - now;
        if (red > best_reduction + eps) {
            best_reduction = red;
            best_cell = {i,j};
        }
    }

    // フォールバック: 候補なしなら outside 戦略に
    if (best_cell.first < 0) {
        return next_greedy_step_adjmax_outside(state, empties, idx_map);
    }

    long long key = ((long long)best_cell.first << 32)
                  | (unsigned)best_cell.second;
    return idx_map.at(key);
}
// 1) p(i,j) が最小のセルを絞り込み  
// 2) その中で、上下左右4近傍の最大確率 adj_max を最大化  
// 3) 置いたときにその adj_max セルの「最大スライド距離」が最も減るセルを絞り込み  
// 4) さらにその中で、上下左右4近傍の「空きマス数」が最大のセルを選ぶ  
int next_greedy_step_trap_chain(
    const StepSimulator::State &state,
    const vector<Cell>         &empties,
    const unordered_map<long long,int> &idx_map
) {
    const double eps = 1e-12;
    int N = state.prob.size();
    static int dr[4] = {-1,1,0,0}, dc[4] = {0,0,-1,1};

    // STEP1: 最小 p を求める
    double min_p = numeric_limits<double>::infinity();
    for (auto &c : empties) {
        if (state.occ[c.r][c.c]) continue;
        min_p = min(min_p, state.prob[c.r][c.c]);
    }

    // STEP2: min_p セルの中で adj_max を最大化→一時候補
    double best_adj_max = -1.0;
    vector<Cell> level2;
    for (auto &c : empties) {
        int i = c.r, j = c.c;
        if (state.occ[i][j]) continue;
        if (fabs(state.prob[i][j] - min_p) > eps) continue;
        double local_max = 0.0;
        for (int d=0; d<4; ++d) {
            int ni = i+dr[d], nj = j+dc[d];
            if (ni>=0&&ni<N&&nj>=0&&nj<N&&!state.occ[ni][nj])
                local_max = max(local_max, state.prob[ni][nj]);
        }
        if (local_max > best_adj_max + eps) {
            best_adj_max = local_max;
            level2.clear();
            level2.push_back(c);
        } else if (fabs(local_max - best_adj_max) < eps) {
            level2.push_back(c);
        }
    }

    // helper: compute slide length
    auto slide_len = [&](int si,int sj,const vector<vector<bool>>& occ_map){
        int maxd = 0;
        for(int d=0;d<4;d++){
            int dist=0, ni=si, nj=sj;
            while(true){
                int ti=ni+dr[d], tj=nj+dc[d];
                if(ti<0||ti>=N||tj<0||tj>=N||occ_map[ti][tj]) break;
                ni=ti; nj=tj; ++dist;
            }
            maxd = max(maxd, dist);
        }
        return maxd;
    };

    // STEP3: trap reduction 最大化 →さらに候補絞り
    double best_reduction = -1.0;
    vector<Cell> level3;
    for (auto &c : level2) {
        int i = c.r, j = c.c;
        // 隣接 max セルを探す
        double local_max=0; pair<int,int> tgt{-1,-1};
        for(int d=0;d<4;d++){
            int ni=i+dr[d], nj=j+dc[d];
            if(ni>=0&&ni<N&&nj>=0&&nj<N&&!state.occ[ni][nj]){
                double q = state.prob[ni][nj];
                if(q > local_max + eps){
                    local_max = q;
                    tgt = {ni,nj};
                }
            }
        }
        if(tgt.first<0) continue;
        double orig = slide_len(tgt.first, tgt.second, state.occ);
        auto occ2 = state.occ;
        occ2[i][j] = true;
        double now  = slide_len(tgt.first, tgt.second, occ2);
        double red  = orig - now;
        if (red > best_reduction + eps) {
            best_reduction = red;
            level3.clear();
            level3.push_back(c);
        } else if (fabs(red - best_reduction) < eps) {
            level3.push_back(c);
        }
    }

    // STEP4: 空きマス隣接数 最大化
    int best_empty_adj = -1;
    pair<int,int> best_cell{-1,-1};
    for (auto &c : level3) {
        int i = c.r, j = c.c;
        int empty_adj = 0;
        for(int d=0;d<4;d++){
            int ni=i+dr[d], nj=j+dc[d];
            if(ni>=0&&ni<N&&nj>=0&&nj<N&&!state.occ[ni][nj]) ++empty_adj;
        }
        if (empty_adj > best_empty_adj) {
            best_empty_adj = empty_adj;
            best_cell = {i,j};
        }
    }

    // フォールバック: もし候補なしなら outside 戦略
    if (best_cell.first < 0) {
        return next_greedy_step_adjmax_outside(state, empties, idx_map);
    }

    ll key = ((ll)best_cell.first<<32) | (unsigned)best_cell.second;
    return idx_map.at(key);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // --- 入力読み込み ---
    cin >> N >> M;
    grid.resize(N);
    for(int i = 0; i < N; i++){
        cin >> grid[i];
    }

    // --- 空セルリストとマップ構築 ---
    empties.clear();
    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            if(grid[i][j] == '.') empties.push_back({i,j});
        }
    }
    T = empties.size();

    unordered_map<long long,int> idx_map;
    idx_map.reserve(T);
    for(int k = 0; k < T; k++){
        long long key = ((long long)empties[k].r<<32)|(unsigned)empties[k].c;
        idx_map[key] = k;
    }

    // --- 初期 State 構築 ---
    vector<vector<double>> prob(N, vector<double>(N,0.0));
    vector<vector<bool>>   occ (N, vector<bool>(N,false));
    double p0 = 1.0 / T;
    for(auto &c: empties) prob[c.r][c.c] = p0;
    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            if(grid[i][j] == '#') occ[i][j] = true;
        }
    }
    StepSimulator sim(N);
    StepSimulator::State init{prob, occ};

    double bestE = -1.0;
    vector<int> bestP;

    // --- Greedy inside ---
    {
        auto state = init;
        vector<int> P;
        P.reserve(T);
        for(int t = 0; t < T; t++){
            int idx = next_greedy_step_adjmax_inside(state, empties, idx_map);
            P.push_back(idx);
            auto cell = empties[idx];
            auto res  = sim.step(state, {cell.r, cell.c});
            state.prob = move(res.next_prob);
            state.occ  = move(res.next_occ);
        }
        double E = compute_expected_sum(P);
        if(E > bestE){
            bestE = E;
            bestP = move(P);
        }
    }

    // --- Greedy outside ---
    {
        auto state = init;
        vector<int> P;
        P.reserve(T);
        for(int t = 0; t < T; t++){
            int idx = next_greedy_step_adjmax_outside(state, empties, idx_map);
            P.push_back(idx);
            auto cell = empties[idx];
            auto res  = sim.step(state, {cell.r, cell.c});
            state.prob = move(res.next_prob);
            state.occ  = move(res.next_occ);
        }
        double E = compute_expected_sum(P);
        if(E > bestE){
            bestE = E;
            bestP = move(P);
        }
    }

    // --- Greedy sum_max (adjprob) ---
    {
        auto state = init;
        vector<int> P;
        P.reserve(T);
        for(int t = 0; t < T; t++){
            int idx = next_greedy_step_adjprob(state, empties, idx_map);
            P.push_back(idx);
            auto cell = empties[idx];
            auto res  = sim.step(state, {cell.r, cell.c});
            state.prob = move(res.next_prob);
            state.occ  = move(res.next_occ);
        }
        double E = compute_expected_sum(P);
        if(E > bestE){
            bestE = E;
            bestP = move(P);
        }
    }
    
     // --- Greedy sum_max (adjprob) ---
    {
        auto state = init;
        vector<int> P;
        P.reserve(T);
        for(int t = 0; t < T; t++){
            int idx = next_greedy_step_trap_chain(state, empties, idx_map);
            P.push_back(idx);
            auto cell = empties[idx];
            auto res  = sim.step(state, {cell.r, cell.c});
            state.prob = move(res.next_prob);
            state.occ  = move(res.next_occ);
        }
        double E = compute_expected_sum(P);
        if(E > bestE){
            bestE = E;
            bestP = move(P);
        }
    }

    // --- 出力 ---
    for(int idx : bestP){
        cout << empties[idx].r << " " << empties[idx].c << "\n";
    }
    cerr << "Best E = " << fixed << setprecision(6) << bestE
         << ", score = " << compute_score(bestE) << "\n";

    return 0;
}

提出情報

提出日時
問題 A - Gamble on Ice
ユーザ koshinM
言語 C++ 17 (gcc 12.2)
得点 145375933
コード長 49719 Byte
結果 AC
実行時間 397 ms
メモリ 4204 KiB

コンパイルエラー

Main.cpp: In function ‘int next_greedy_step_complex(const StepSimulator::State&, const std::vector<Cell>&, const std::unordered_map<long long int, int>&)’:
Main.cpp:378:31: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  378 |             if (ni >= 0 && ni < state.occ.size()
      |                            ~~~^~~~~~~~~~~~~~~~~~
Main.cpp:379:31: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  379 |              && nj >= 0 && nj < state.occ.size()
      |                            ~~~^~~~~~~~~~~~~~~~~~
Main.cpp: In function ‘int next_greedy_step_center_first(const StepSimulator::State&, const std::vector<Cell>&, const std::unordered_map<long long int, int>&)’:
Main.cpp:448:31: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  448 |             if (ni >= 0 && ni < state.occ.size()
      |                            ~~~^~~~~~~~~~~~~~~~~~
Main.cpp:449:31: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  449 |              && nj >= 0 && nj < state.occ.size()
      |                            ~~~^~~~~~~~~~~~~~~~~~
Main.cpp: In function ‘int next_greedy_step_custom_outside(const StepSimulator::State&, const std::vector<Cell>&, const std::unordered_map<long long int, int>&)’:
Main.cpp:516:28: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  516 |             if (ni>=0 && ni<state.occ.size() &&
      |                          ~~^~~~~~~~~~~~~~~~~
Main.cpp:517:28: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  517 |                 nj>=0 && nj<state.occ.size() &&
      |                          ~~^~~~~~~~~~~~~~~~~
Main.cpp: In function ‘int next_greedy_step_custom_inside(const StepSimulator::State&, const std::vector<Cell>&, const std::unordered_map<long long int, int>&)’:
Main.cpp:588:31: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  588 |             if (ni >= 0 && ni < state.occ.size() &&
      |                            ~~~^~~~~~~~~~~~~~~~~~
Main.cpp:589:31: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  589 |                 nj >= 0 && nj < state.occ.size() &&
      |                            ~~~^~~~~~~~~~~~~~~~~~
Main.cpp: In function ‘int next_greedy_step_ratio_outside(const StepSimulator::State&, const std::vector<Cell>&, const std::unordered_map<long long int, int>&)’:
Main.cpp:792:27: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  792 |             if(ni>=0 && ni<state.occ.size() &&
      |                         ~~^~~~~~~~~~~~~~~~~
Main.cpp:793:27: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<std::vector<bool> >::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  793 |                nj>=0 && nj<state.occ.size() &&
      |                         ~~^~~~~~~~~~~~~~~~~
Main.cpp: In function ‘int next_greedy_step_enhanced(const StepSimulator::State&, const std::vector<Cell>&, const std::unordered_map<long long int, int>&, StepSimulator&)’:
Main.cpp:847:33: warning: unused parameter ‘sim’ [-Wunused-parameter]
  847 |     StepSimulator              &sim
      |     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~

ジャッジ結果

セット名 test_ALL
得点 / 配点 145375933 / 150000000
結果
AC × 150
セット名 テストケース
test_ALL test_0000.txt, test_0001.txt, test_0002.txt, test_0003.txt, test_0004.txt, test_0005.txt, test_0006.txt, test_0007.txt, test_0008.txt, test_0009.txt, test_0010.txt, test_0011.txt, test_0012.txt, test_0013.txt, test_0014.txt, test_0015.txt, test_0016.txt, test_0017.txt, test_0018.txt, test_0019.txt, test_0020.txt, test_0021.txt, test_0022.txt, test_0023.txt, test_0024.txt, test_0025.txt, test_0026.txt, test_0027.txt, test_0028.txt, test_0029.txt, test_0030.txt, test_0031.txt, test_0032.txt, test_0033.txt, test_0034.txt, test_0035.txt, test_0036.txt, test_0037.txt, test_0038.txt, test_0039.txt, test_0040.txt, test_0041.txt, test_0042.txt, test_0043.txt, test_0044.txt, test_0045.txt, test_0046.txt, test_0047.txt, test_0048.txt, test_0049.txt, test_0050.txt, test_0051.txt, test_0052.txt, test_0053.txt, test_0054.txt, test_0055.txt, test_0056.txt, test_0057.txt, test_0058.txt, test_0059.txt, test_0060.txt, test_0061.txt, test_0062.txt, test_0063.txt, test_0064.txt, test_0065.txt, test_0066.txt, test_0067.txt, test_0068.txt, test_0069.txt, test_0070.txt, test_0071.txt, test_0072.txt, test_0073.txt, test_0074.txt, test_0075.txt, test_0076.txt, test_0077.txt, test_0078.txt, test_0079.txt, test_0080.txt, test_0081.txt, test_0082.txt, test_0083.txt, test_0084.txt, test_0085.txt, test_0086.txt, test_0087.txt, test_0088.txt, test_0089.txt, test_0090.txt, test_0091.txt, test_0092.txt, test_0093.txt, test_0094.txt, test_0095.txt, test_0096.txt, test_0097.txt, test_0098.txt, test_0099.txt, test_0100.txt, test_0101.txt, test_0102.txt, test_0103.txt, test_0104.txt, test_0105.txt, test_0106.txt, test_0107.txt, test_0108.txt, test_0109.txt, test_0110.txt, test_0111.txt, test_0112.txt, test_0113.txt, test_0114.txt, test_0115.txt, test_0116.txt, test_0117.txt, test_0118.txt, test_0119.txt, test_0120.txt, test_0121.txt, test_0122.txt, test_0123.txt, test_0124.txt, test_0125.txt, test_0126.txt, test_0127.txt, test_0128.txt, test_0129.txt, test_0130.txt, test_0131.txt, test_0132.txt, test_0133.txt, test_0134.txt, test_0135.txt, test_0136.txt, test_0137.txt, test_0138.txt, test_0139.txt, test_0140.txt, test_0141.txt, test_0142.txt, test_0143.txt, test_0144.txt, test_0145.txt, test_0146.txt, test_0147.txt, test_0148.txt, test_0149.txt
ケース名 結果 実行時間 メモリ
test_0000.txt AC 397 ms 3984 KiB
test_0001.txt AC 336 ms 4060 KiB
test_0002.txt AC 369 ms 4064 KiB
test_0003.txt AC 335 ms 4184 KiB
test_0004.txt AC 367 ms 4176 KiB
test_0005.txt AC 384 ms 4020 KiB
test_0006.txt AC 379 ms 3968 KiB
test_0007.txt AC 352 ms 3960 KiB
test_0008.txt AC 388 ms 4064 KiB
test_0009.txt AC 383 ms 4036 KiB
test_0010.txt AC 348 ms 3968 KiB
test_0011.txt AC 395 ms 4024 KiB
test_0012.txt AC 370 ms 4184 KiB
test_0013.txt AC 380 ms 4072 KiB
test_0014.txt AC 381 ms 3968 KiB
test_0015.txt AC 366 ms 3964 KiB
test_0016.txt AC 373 ms 4192 KiB
test_0017.txt AC 346 ms 4132 KiB
test_0018.txt AC 321 ms 4036 KiB
test_0019.txt AC 370 ms 3960 KiB
test_0020.txt AC 381 ms 4180 KiB
test_0021.txt AC 363 ms 4028 KiB
test_0022.txt AC 367 ms 4012 KiB
test_0023.txt AC 378 ms 4140 KiB
test_0024.txt AC 329 ms 4172 KiB
test_0025.txt AC 373 ms 4180 KiB
test_0026.txt AC 384 ms 4196 KiB
test_0027.txt AC 383 ms 4136 KiB
test_0028.txt AC 360 ms 4200 KiB
test_0029.txt AC 373 ms 4060 KiB
test_0030.txt AC 394 ms 4140 KiB
test_0031.txt AC 355 ms 4016 KiB
test_0032.txt AC 335 ms 4140 KiB
test_0033.txt AC 360 ms 4180 KiB
test_0034.txt AC 336 ms 3972 KiB
test_0035.txt AC 330 ms 3956 KiB
test_0036.txt AC 377 ms 3964 KiB
test_0037.txt AC 375 ms 4180 KiB
test_0038.txt AC 328 ms 4056 KiB
test_0039.txt AC 361 ms 4060 KiB
test_0040.txt AC 352 ms 4016 KiB
test_0041.txt AC 309 ms 4124 KiB
test_0042.txt AC 349 ms 3960 KiB
test_0043.txt AC 352 ms 4028 KiB
test_0044.txt AC 371 ms 4060 KiB
test_0045.txt AC 377 ms 4184 KiB
test_0046.txt AC 366 ms 3964 KiB
test_0047.txt AC 319 ms 4136 KiB
test_0048.txt AC 386 ms 4204 KiB
test_0049.txt AC 366 ms 4080 KiB
test_0050.txt AC 325 ms 4172 KiB
test_0051.txt AC 365 ms 4132 KiB
test_0052.txt AC 384 ms 4176 KiB
test_0053.txt AC 336 ms 4024 KiB
test_0054.txt AC 395 ms 4024 KiB
test_0055.txt AC 313 ms 4180 KiB
test_0056.txt AC 364 ms 4136 KiB
test_0057.txt AC 357 ms 4132 KiB
test_0058.txt AC 337 ms 4132 KiB
test_0059.txt AC 349 ms 4016 KiB
test_0060.txt AC 388 ms 4168 KiB
test_0061.txt AC 320 ms 4164 KiB
test_0062.txt AC 385 ms 4032 KiB
test_0063.txt AC 383 ms 4020 KiB
test_0064.txt AC 352 ms 4180 KiB
test_0065.txt AC 391 ms 3968 KiB
test_0066.txt AC 384 ms 3968 KiB
test_0067.txt AC 378 ms 4144 KiB
test_0068.txt AC 360 ms 4144 KiB
test_0069.txt AC 390 ms 4144 KiB
test_0070.txt AC 376 ms 3968 KiB
test_0071.txt AC 315 ms 4168 KiB
test_0072.txt AC 379 ms 4140 KiB
test_0073.txt AC 317 ms 4132 KiB
test_0074.txt AC 389 ms 4032 KiB
test_0075.txt AC 317 ms 4128 KiB
test_0076.txt AC 385 ms 3976 KiB
test_0077.txt AC 309 ms 3956 KiB
test_0078.txt AC 332 ms 4052 KiB
test_0079.txt AC 382 ms 4132 KiB
test_0080.txt AC 381 ms 4184 KiB
test_0081.txt AC 331 ms 4008 KiB
test_0082.txt AC 393 ms 4036 KiB
test_0083.txt AC 326 ms 4016 KiB
test_0084.txt AC 312 ms 4020 KiB
test_0085.txt AC 358 ms 4024 KiB
test_0086.txt AC 364 ms 3964 KiB
test_0087.txt AC 338 ms 4020 KiB
test_0088.txt AC 390 ms 4052 KiB
test_0089.txt AC 369 ms 3964 KiB
test_0090.txt AC 329 ms 4164 KiB
test_0091.txt AC 310 ms 4064 KiB
test_0092.txt AC 369 ms 3972 KiB
test_0093.txt AC 375 ms 3968 KiB
test_0094.txt AC 392 ms 4148 KiB
test_0095.txt AC 346 ms 4132 KiB
test_0096.txt AC 364 ms 4136 KiB
test_0097.txt AC 313 ms 4008 KiB
test_0098.txt AC 329 ms 3976 KiB
test_0099.txt AC 352 ms 4188 KiB
test_0100.txt AC 380 ms 4136 KiB
test_0101.txt AC 363 ms 4128 KiB
test_0102.txt AC 387 ms 4184 KiB
test_0103.txt AC 349 ms 4044 KiB
test_0104.txt AC 323 ms 4012 KiB
test_0105.txt AC 356 ms 4136 KiB
test_0106.txt AC 394 ms 4032 KiB
test_0107.txt AC 368 ms 4180 KiB
test_0108.txt AC 379 ms 4184 KiB
test_0109.txt AC 337 ms 4012 KiB
test_0110.txt AC 359 ms 3980 KiB
test_0111.txt AC 383 ms 4184 KiB
test_0112.txt AC 383 ms 3964 KiB
test_0113.txt AC 374 ms 4176 KiB
test_0114.txt AC 358 ms 4136 KiB
test_0115.txt AC 351 ms 4032 KiB
test_0116.txt AC 385 ms 4020 KiB
test_0117.txt AC 373 ms 4132 KiB
test_0118.txt AC 367 ms 4132 KiB
test_0119.txt AC 352 ms 4012 KiB
test_0120.txt AC 308 ms 4016 KiB
test_0121.txt AC 386 ms 4016 KiB
test_0122.txt AC 349 ms 4132 KiB
test_0123.txt AC 327 ms 4124 KiB
test_0124.txt AC 328 ms 4012 KiB
test_0125.txt AC 345 ms 4016 KiB
test_0126.txt AC 353 ms 4060 KiB
test_0127.txt AC 348 ms 4024 KiB
test_0128.txt AC 346 ms 4176 KiB
test_0129.txt AC 382 ms 4180 KiB
test_0130.txt AC 346 ms 4024 KiB
test_0131.txt AC 334 ms 4020 KiB
test_0132.txt AC 327 ms 4020 KiB
test_0133.txt AC 322 ms 4172 KiB
test_0134.txt AC 325 ms 4168 KiB
test_0135.txt AC 314 ms 4008 KiB
test_0136.txt AC 366 ms 4164 KiB
test_0137.txt AC 358 ms 4136 KiB
test_0138.txt AC 336 ms 4008 KiB
test_0139.txt AC 385 ms 4132 KiB
test_0140.txt AC 354 ms 4012 KiB
test_0141.txt AC 321 ms 4128 KiB
test_0142.txt AC 382 ms 3968 KiB
test_0143.txt AC 363 ms 3964 KiB
test_0144.txt AC 374 ms 4136 KiB
test_0145.txt AC 390 ms 4140 KiB
test_0146.txt AC 367 ms 4068 KiB
test_0147.txt AC 333 ms 4180 KiB
test_0148.txt AC 357 ms 4024 KiB
test_0149.txt AC 359 ms 4020 KiB