Submission #70298523


Source Code Expand

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#include <iomanip>
#include <numeric>
#include <random> // 乱数生成
#include <chrono> // 時間計測
#include <queue> 

using namespace std;
using ll = long long;
const ll INF = 1e18;

// --- 実行時間制限 (秒) ---
const double TIME_LIMIT_SEC = 1.97; 

// --- 焼きなましパラメータ ---
const double START_TEMP = 12.0; 
const double END_TEMP = 1.0;    

// --- ビームサーチ パラメータ ---
const int BEAM_WIDTH = 10; 

// 乱数生成器
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
uniform_real_distribution<double> real_dist(0.0, 1.0);

// 時間計測用
auto start_time = chrono::steady_clock::now();


// 宝箱jを開けるコストと攻撃シーケンスを計算
struct CostResult {
    map<int, ll> durability_updates; // <weapon_idx, use_count>
    vector<pair<int, int>> attacks_sequence;
};

/**
 * @brief 宝箱jを開ける最小コストを「機会費用」に基づいて計算 (v8準拠)
 * @param current_durability (const参照)
 */
CostResult calculate_cost(
    int j,
    const vector<ll>& H,
    const vector<vector<ll>>& A,
    const vector<bool>& open_set,
    const vector<ll>& current_durability, // const&
    const vector<double>& weapon_value 
) {
    CostResult res;
    ll h = H[j];
    if (h <= 0) return res;

    vector<pair<double, int>> usable_weapons; // {実質コスト, 武器idx}
    int N = H.size();
    for (int w = 0; w < N; ++w) {
        // 「今使える」武器 (open_set[w] かつ current_durability[w] > 0)
        if (open_set[w] && current_durability[w] > 0 && A[w][j] > 1) {
            double damage = (double)A[w][j];
            double value = weapon_value[w];
            double real_cost = value / damage; 
            usable_weapons.push_back({real_cost, w});
        }
    }

    // 「実質コスト」が低い順にソート O(N log N)
    sort(usable_weapons.begin(), usable_weapons.end());

    for (auto& p : usable_weapons) {
        double real_cost_per_hit = p.first;
        int w_idx = p.second;
        ll damage = A[w_idx][j];

        // 温存ロジック: 実質コストが 1.0 以上なら、素手で殴るのと変わらない(か損)
        // (武器が余る原因だが、v15 の浪費よりはマシという判断)
        if (real_cost_per_hit >= 1.0) {
            break; 
        }

        ll needed_hits = (h + damage - 1) / damage;
        ll use_count = min(current_durability[w_idx], needed_hits); 

        for (int k = 0; k < use_count; ++k) {
            res.attacks_sequence.push_back({w_idx, j});
        }
        h -= use_count * damage;
        res.durability_updates[w_idx] = use_count; // 使った回数を返す
        
        if (h <= 0) break;
    }

    // 残りはすべて素手で攻撃
    if (h > 0) {
        for (int k = 0; k < h; ++k) {
            res.attacks_sequence.push_back({-1, j});
        }
    }
    return res;
}

// ビームサーチで管理する「状態」
struct State {
    vector<bool> open_set;
    vector<ll> current_durability; // 今使える耐久値
    vector<ll> future_durability; // 将来手に入る耐久値 (Cの残り)
    ll total_cost;                  
    int parent_index;
    vector<pair<int, int>> last_attack_log;
    int last_opened_box; 

    bool operator<(const State& other) const {
        return total_cost < other.total_cost;
    }
};

/**
 * @brief 焼きなまし法の「評価関数」 O(N^2 log N) (v17)
 */
pair<ll, vector<pair<int, int>>> evaluate(
    int N,
    const vector<int>& order, 
    const vector<ll>& H,
    const vector<ll>& C,
    const vector<vector<ll>>& A,
    const vector<double>& weapon_value // 機会費用
) {
    vector<bool> open_set(N, false);
    vector<ll> current_durability(N, 0); // 今使える耐久値
    vector<ll> future_durability = C;    // 将来手に入る耐久値
    
    vector<pair<int, int>> total_log;
    ll total_cost = 0;

    for (int j : order) { 
        // 「今使える耐久値」で「機会費用」コストを計算
        CostResult res = calculate_cost(j, H, A, open_set, current_durability, weapon_value);
        
        total_cost += res.attacks_sequence.size();
        total_log.insert(total_log.end(), res.attacks_sequence.begin(), res.attacks_sequence.end());

        // 状態更新 (v15の厳密ロジック)
        for (auto const& [w_idx, use_count] : res.durability_updates) {
            current_durability[w_idx] -= use_count;
        }
        open_set[j] = true;
        current_durability[j] = future_durability[j]; 
        future_durability[j] = 0; 
    }
    return {total_cost, total_log};
}


int main() {
    int N;
    cin >> N; 

    vector<ll> H(N), C(N);
    for (int i = 0; i < N; ++i) cin >> H[i];
    for (int i = 0; i < N; ++i) cin >> C[i];

    vector<vector<ll>> A(N, vector<ll>(N));
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < N; ++j) {
            cin >> A[i][j];
        }
    }

    // 1. 前計算: 武器の「価値」を計算 (v8準拠)
    vector<double> weapon_value(N);
    for (int w = 0; w < N; ++w) {
        double total_saving = 0;
        for (int k = 0; k < N; ++k) {
            total_saving += max(0LL, A[w][k] - 1);
        }
        weapon_value[w] = 1.0 + (total_saving / (double)N);
    }

    // --- フェーズ1: ビームサーチ (初期解 P の生成) ---
    vector<int> best_order; 
    ll best_score = INF;
    
    { // ビームサーチのスコープ
        vector<vector<State>> beam_history(N + 1);

        {
            State initial_state;
            initial_state.open_set.resize(N, false);
            initial_state.current_durability.resize(N, 0);
            initial_state.future_durability = C;
            initial_state.total_cost = 0;
            initial_state.parent_index = -1;
            initial_state.last_opened_box = -1;
            beam_history[0].push_back(initial_state);
        }

        for (int step = 0; step < N; ++step) {
            vector<State> next_beam_candidates;
            for (int parent_idx = 0; parent_idx < beam_history[step].size(); ++parent_idx) {
                const auto& parent_state = beam_history[step][parent_idx];
                for (int j = 0; j < N; ++j) {
                    if (parent_state.open_set[j]) continue;

                    // v17 のコスト計算 (機会費用)
                    CostResult res = calculate_cost(j, H, A, 
                                                    parent_state.open_set, 
                                                    parent_state.current_durability, 
                                                    weapon_value); 
                    State new_state;
                    new_state.open_set = parent_state.open_set;
                    new_state.open_set[j] = true;
                    
                    // v15 の厳密なシミュレーションロジック
                    new_state.current_durability = parent_state.current_durability;
                    new_state.future_durability = parent_state.future_durability;
                    for (auto const& [w_idx, use_count] : res.durability_updates) {
                        new_state.current_durability[w_idx] -= use_count;
                    }
                    new_state.current_durability[j] = new_state.future_durability[j];
                    new_state.future_durability[j] = 0;
                    
                    new_state.total_cost = parent_state.total_cost + res.attacks_sequence.size();
                    new_state.parent_index = parent_idx;
                    new_state.last_attack_log = std::move(res.attacks_sequence);
                    new_state.last_opened_box = j; 

                    next_beam_candidates.push_back(std::move(new_state));
                }
            }
            sort(next_beam_candidates.begin(), next_beam_candidates.end());
            beam_history[step + 1].clear();
            for (int i = 0; i < min((int)next_beam_candidates.size(), BEAM_WIDTH); ++i) {
                beam_history[step + 1].push_back(std::move(next_beam_candidates[i]));
            }
        }

        // --- 「順番 P」の復元 ---
        int best_final_index = -1;
        if (!beam_history[N].empty()) {
            for (int i = 0; i < beam_history[N].size(); ++i) {
                if (beam_history[N][i].total_cost < best_score) {
                    best_score = beam_history[N][i].total_cost;
                    best_final_index = i;
                }
            }
        }
        
        if (best_final_index != -1) {
            int current_parent_idx = best_final_index; 
            for (int step = N; step >= 1; --step) {
                const auto& s = beam_history[step][current_parent_idx];
                best_order.push_back(s.last_opened_box); 
                current_parent_idx = s.parent_index;
            }
            reverse(best_order.begin(), best_order.end()); 
        }
    } // ビームサーチ スコープ終了

    if (best_score == INF) {
        return 0; // 解なし
    }
    
    vector<int> current_order = best_order;
    ll current_score = best_score;
    vector<pair<int, int>> best_log;
    {
        auto [score, log] = evaluate(N, best_order, H, C, A, weapon_value);
        best_log = std::move(log);
    }

    
    // --- フェーズ2: 焼きなまし法 (解の改善) ---
    uniform_int_distribution<int> idx_dist(0, N - 1);
    
    int iteration = 0;
    while (true) {
        iteration++;
        
        if (iteration % 10 == 0) {
            auto now = chrono::steady_clock::now();
            double elapsed_sec = chrono::duration<double>(now - start_time).count();
            if (elapsed_sec > TIME_LIMIT_SEC) {
                break;
            }
        }
        
        int i = idx_dist(rng);
        int j = idx_dist(rng);
        if (i == j) continue;
        
        swap(current_order[i], current_order[j]); 

        // 評価 O(N^2 log N)
        auto [new_score, new_log] = evaluate(N, current_order, H, C, A, weapon_value);
        
        double delta = new_score - current_score;
        
        auto now = chrono::steady_clock::now();
        double time_ratio = chrono::duration<double>(now - start_time).count() / TIME_LIMIT_SEC;
        double temp = START_TEMP + (END_TEMP - START_TEMP) * time_ratio;
        
        if (delta < 0 || real_dist(rng) < exp(-delta / temp)) {
            current_score = new_score;
            if (new_score < best_score) {
                best_score = new_score;
                best_order = current_order; // 順番を保存
                best_log = std::move(new_log); // ログを保存
            }
        } else {
            swap(current_order[i], current_order[j]); // 元に戻す
        }
    }
    
    // --- フェーズ3: 最終出力 ---
    // SA で見つけた best_log をそのまま出力
    for (const auto& attack : best_log) {
        cout << attack.first << " " << attack.second << endl;
    }
    cerr << (int)best_log.size() << endl;

    return 0;
}

Submission Info

Submission Time
Task A - Weakpoint
User mdstoy
Language C++ 20 (gcc 12.2)
Score 7922082
Code Size 11476 Byte
Status AC
Exec Time 1989 ms
Memory 17636 KiB

Compile Error

Main.cpp: In function ‘int main()’:
Main.cpp:202:49: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<State>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  202 |             for (int parent_idx = 0; parent_idx < beam_history[step].size(); ++parent_idx) {
      |                                      ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:243:31: warning: comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<State>::size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
  243 |             for (int i = 0; i < beam_history[N].size(); ++i) {
      |                             ~~^~~~~~~~~~~~~~~~~~~~~~~~

Judge Result

Set Name test_ALL
Score / Max Score 7922082 / 15000000
Status
AC × 150
Set Name Test Cases
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
Case Name Status Exec Time Memory
test_0000.txt AC 1981 ms 17096 KiB
test_0001.txt AC 1982 ms 17116 KiB
test_0002.txt AC 1981 ms 17384 KiB
test_0003.txt AC 1983 ms 16920 KiB
test_0004.txt AC 1980 ms 17260 KiB
test_0005.txt AC 1976 ms 16836 KiB
test_0006.txt AC 1980 ms 17264 KiB
test_0007.txt AC 1983 ms 17216 KiB
test_0008.txt AC 1981 ms 17300 KiB
test_0009.txt AC 1980 ms 17064 KiB
test_0010.txt AC 1982 ms 16936 KiB
test_0011.txt AC 1978 ms 17428 KiB
test_0012.txt AC 1978 ms 17140 KiB
test_0013.txt AC 1981 ms 17136 KiB
test_0014.txt AC 1981 ms 17124 KiB
test_0015.txt AC 1980 ms 17212 KiB
test_0016.txt AC 1980 ms 16960 KiB
test_0017.txt AC 1980 ms 16896 KiB
test_0018.txt AC 1985 ms 17592 KiB
test_0019.txt AC 1981 ms 17200 KiB
test_0020.txt AC 1979 ms 17224 KiB
test_0021.txt AC 1983 ms 16988 KiB
test_0022.txt AC 1980 ms 17264 KiB
test_0023.txt AC 1980 ms 17212 KiB
test_0024.txt AC 1982 ms 17608 KiB
test_0025.txt AC 1982 ms 17368 KiB
test_0026.txt AC 1979 ms 17144 KiB
test_0027.txt AC 1981 ms 17616 KiB
test_0028.txt AC 1977 ms 16400 KiB
test_0029.txt AC 1979 ms 17092 KiB
test_0030.txt AC 1980 ms 17212 KiB
test_0031.txt AC 1982 ms 17312 KiB
test_0032.txt AC 1983 ms 17356 KiB
test_0033.txt AC 1981 ms 17008 KiB
test_0034.txt AC 1980 ms 16976 KiB
test_0035.txt AC 1979 ms 17392 KiB
test_0036.txt AC 1984 ms 16920 KiB
test_0037.txt AC 1980 ms 17264 KiB
test_0038.txt AC 1982 ms 17460 KiB
test_0039.txt AC 1979 ms 17340 KiB
test_0040.txt AC 1978 ms 17148 KiB
test_0041.txt AC 1978 ms 16484 KiB
test_0042.txt AC 1986 ms 17172 KiB
test_0043.txt AC 1982 ms 17340 KiB
test_0044.txt AC 1979 ms 16832 KiB
test_0045.txt AC 1980 ms 17048 KiB
test_0046.txt AC 1982 ms 16740 KiB
test_0047.txt AC 1977 ms 16980 KiB
test_0048.txt AC 1983 ms 17584 KiB
test_0049.txt AC 1984 ms 17356 KiB
test_0050.txt AC 1983 ms 17500 KiB
test_0051.txt AC 1977 ms 17416 KiB
test_0052.txt AC 1979 ms 17624 KiB
test_0053.txt AC 1981 ms 17188 KiB
test_0054.txt AC 1976 ms 16516 KiB
test_0055.txt AC 1980 ms 17136 KiB
test_0056.txt AC 1978 ms 17356 KiB
test_0057.txt AC 1982 ms 17224 KiB
test_0058.txt AC 1985 ms 17312 KiB
test_0059.txt AC 1976 ms 16788 KiB
test_0060.txt AC 1981 ms 17044 KiB
test_0061.txt AC 1982 ms 17448 KiB
test_0062.txt AC 1985 ms 17192 KiB
test_0063.txt AC 1989 ms 17388 KiB
test_0064.txt AC 1980 ms 16860 KiB
test_0065.txt AC 1982 ms 17008 KiB
test_0066.txt AC 1979 ms 17200 KiB
test_0067.txt AC 1982 ms 17352 KiB
test_0068.txt AC 1980 ms 17280 KiB
test_0069.txt AC 1981 ms 17496 KiB
test_0070.txt AC 1980 ms 17316 KiB
test_0071.txt AC 1981 ms 17348 KiB
test_0072.txt AC 1983 ms 17316 KiB
test_0073.txt AC 1979 ms 17372 KiB
test_0074.txt AC 1982 ms 17468 KiB
test_0075.txt AC 1983 ms 16984 KiB
test_0076.txt AC 1983 ms 17264 KiB
test_0077.txt AC 1982 ms 17492 KiB
test_0078.txt AC 1976 ms 17216 KiB
test_0079.txt AC 1980 ms 17400 KiB
test_0080.txt AC 1978 ms 16920 KiB
test_0081.txt AC 1981 ms 17268 KiB
test_0082.txt AC 1979 ms 17376 KiB
test_0083.txt AC 1984 ms 17156 KiB
test_0084.txt AC 1980 ms 17312 KiB
test_0085.txt AC 1982 ms 16884 KiB
test_0086.txt AC 1981 ms 16852 KiB
test_0087.txt AC 1980 ms 17024 KiB
test_0088.txt AC 1984 ms 17460 KiB
test_0089.txt AC 1980 ms 17036 KiB
test_0090.txt AC 1980 ms 17272 KiB
test_0091.txt AC 1982 ms 17332 KiB
test_0092.txt AC 1980 ms 17200 KiB
test_0093.txt AC 1984 ms 17636 KiB
test_0094.txt AC 1983 ms 16472 KiB
test_0095.txt AC 1981 ms 17224 KiB
test_0096.txt AC 1978 ms 16808 KiB
test_0097.txt AC 1978 ms 16572 KiB
test_0098.txt AC 1981 ms 17340 KiB
test_0099.txt AC 1980 ms 16932 KiB
test_0100.txt AC 1977 ms 17340 KiB
test_0101.txt AC 1979 ms 17176 KiB
test_0102.txt AC 1982 ms 17180 KiB
test_0103.txt AC 1977 ms 17308 KiB
test_0104.txt AC 1977 ms 16700 KiB
test_0105.txt AC 1987 ms 17512 KiB
test_0106.txt AC 1986 ms 17616 KiB
test_0107.txt AC 1979 ms 16876 KiB
test_0108.txt AC 1978 ms 17092 KiB
test_0109.txt AC 1977 ms 17104 KiB
test_0110.txt AC 1981 ms 17236 KiB
test_0111.txt AC 1980 ms 17164 KiB
test_0112.txt AC 1978 ms 17420 KiB
test_0113.txt AC 1979 ms 17092 KiB
test_0114.txt AC 1982 ms 17292 KiB
test_0115.txt AC 1980 ms 17380 KiB
test_0116.txt AC 1978 ms 17112 KiB
test_0117.txt AC 1980 ms 17232 KiB
test_0118.txt AC 1982 ms 17364 KiB
test_0119.txt AC 1979 ms 17340 KiB
test_0120.txt AC 1977 ms 16420 KiB
test_0121.txt AC 1981 ms 17368 KiB
test_0122.txt AC 1981 ms 17240 KiB
test_0123.txt AC 1982 ms 16916 KiB
test_0124.txt AC 1982 ms 16964 KiB
test_0125.txt AC 1977 ms 17016 KiB
test_0126.txt AC 1976 ms 17040 KiB
test_0127.txt AC 1981 ms 17340 KiB
test_0128.txt AC 1981 ms 17408 KiB
test_0129.txt AC 1975 ms 16892 KiB
test_0130.txt AC 1981 ms 17296 KiB
test_0131.txt AC 1981 ms 17136 KiB
test_0132.txt AC 1982 ms 17432 KiB
test_0133.txt AC 1982 ms 17508 KiB
test_0134.txt AC 1980 ms 16908 KiB
test_0135.txt AC 1982 ms 17276 KiB
test_0136.txt AC 1982 ms 17380 KiB
test_0137.txt AC 1981 ms 17368 KiB
test_0138.txt AC 1981 ms 17140 KiB
test_0139.txt AC 1982 ms 17376 KiB
test_0140.txt AC 1982 ms 17400 KiB
test_0141.txt AC 1976 ms 17368 KiB
test_0142.txt AC 1984 ms 17436 KiB
test_0143.txt AC 1979 ms 17396 KiB
test_0144.txt AC 1980 ms 17052 KiB
test_0145.txt AC 1983 ms 17216 KiB
test_0146.txt AC 1979 ms 16972 KiB
test_0147.txt AC 1979 ms 17164 KiB
test_0148.txt AC 1979 ms 17340 KiB
test_0149.txt AC 1978 ms 17268 KiB