結果

問題 No.1242 高橋君とすごろく
ユーザー qwewe
提出日時 2025-05-14 13:23:28
言語 C++17
(gcc 13.3.0 + boost 1.87.0)
結果
MLE  
実行時間 -
コード長 5,293 bytes
コンパイル時間 954 ms
コンパイル使用メモリ 94,860 KB
実行使用メモリ 814,720 KB
最終ジャッジ日時 2025-05-14 13:25:18
合計ジャッジ時間 3,441 ms
ジャッジサーバーID
(参考情報)
judge5 / judge2
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 4
other AC * 6 MLE * 1 -- * 17
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <map>

// Global variables to be accessible by the recursive helper function
long long N_val;
std::set<long long> A_set; // Set of game over cells
std::vector<long long> P_crit_sorted_vec; // Sorted list of critical points
std::map<long long, bool> dp_map; // DP values for critical points
std::map<long long, bool> memo_local_dp; // Memoized DP values for non-critical (gap) points

// Recursive function to get the DP value for a given position
bool get_value_for(long long pos) {
    if (pos == N_val) { // Reached goal
        return true;
    }
    if (A_set.count(pos)) { // Landed on a game over cell
        return false;
    }

    // Check if value is already computed for a critical point
    if (dp_map.count(pos)) {
        return dp_map.at(pos);
    }
    // Check if value is already memoized for a non-critical point
    if (memo_local_dp.count(pos)) {
        return memo_local_dp.at(pos);
    }

    // Position is non-critical, and its value is not yet computed.
    // Calculate it using the DP recurrence.
    bool res_pos_survives_all_rolls = true;
    for (int x = 1; x <= 6; ++x) { // Iterate through all possible dice rolls
        bool can_survive_this_roll = false;
        
        // Option 1: Move x cells
        long long next1 = std::min(pos + x, N_val);
        if (!A_set.count(next1)) { // If next1 is not a game over cell
            if (get_value_for(next1)) { // Check if we can win from next1
                can_survive_this_roll = true;
            }
        }

        // Option 2: Move 7-x cells (if Option 1 was not safe or not chosen)
        if (!can_survive_this_roll) {
            long long next2 = std::min(pos + (7 - x), N_val);
            if (!A_set.count(next2)) { // If next2 is not a game over cell
                if (get_value_for(next2)) { // Check if we can win from next2
                    can_survive_this_roll = true;
                }
            }
        }
        
        if (!can_survive_this_roll) { // For this dice roll x, no safe move exists
            res_pos_survives_all_rolls = false;
            break; 
        }
    }
    
    // Memoize and return the computed value for this non-critical point
    memo_local_dp[pos] = res_pos_survives_all_rolls;
    return res_pos_survives_all_rolls;
}

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

    int K_val_int; // K is int according to constraints usually
    std::cin >> N_val >> K_val_int;

    for (int i = 0; i < K_val_int; ++i) {
        long long تعلمنا_a;
        std::cin >> تعلمنا_a;
        A_set.insert(تعلمنا_a);
    }

    // Construct the set of critical points
    std::set<long long> p_crit_set;
    p_crit_set.insert(1); // Starting cell
    p_crit_set.insert(N_val); // Goal cell

    for (long long val_a : A_set) { // Game over cells
        p_crit_set.insert(val_a);
        for (int d = 1; d <= 6; ++d) { // Cells before game over cells
            if (val_a - d >= 1) {
                p_crit_set.insert(val_a - d);
            }
        }
    }
    for (int d = 1; d <= 6; ++d) { // Cells before N
        if (N_val - d >= 1) {
            p_crit_set.insert(N_val - d);
        }
    }
    
    // Convert set to sorted vector (set iteration is sorted)
    for(long long val : p_crit_set) {
        P_crit_sorted_vec.push_back(val);
    }
    // P_crit_sorted_vec is already sorted because std::set iterates in sorted order.

    // Iterate critical points from right to left (largest to smallest)
    for (int i = P_crit_sorted_vec.size() - 1; i >= 0; --i) {
        long long current_p = P_crit_sorted_vec[i];
        
        bool current_p_dp_value;
        if (current_p == N_val) {
            current_p_dp_value = true;
        } else if (A_set.count(current_p)) {
            current_p_dp_value = false;
        } else {
            // Calculate DP value using the recurrence (same logic as in get_value_for)
            bool survives_all_rolls = true;
            for (int x = 1; x <= 6; ++x) {
                bool can_survive_this_roll = false;
                
                long long next1 = std::min(current_p + x, N_val);
                if (!A_set.count(next1)) {
                    if (get_value_for(next1)) {
                        can_survive_this_roll = true;
                    }
                }

                if (!can_survive_this_roll) {
                    long long next2 = std::min(current_p + (7 - x), N_val);
                     if (!A_set.count(next2)) {
                        if (get_value_for(next2)) {
                            can_survive_this_roll = true;
                        }
                    }
                }
                
                if (!can_survive_this_roll) {
                    survives_all_rolls = false;
                    break;
                }
            }
            current_p_dp_value = survives_all_rolls;
        }
        dp_map[current_p] = current_p_dp_value;
    }

    // The answer is dp[1]
    if (get_value_for(1)) { // get_value_for(1) will use dp_map[1] as 1 is critical
        std::cout << "Yes" << std::endl;
    } else {
        std::cout << "No" << std::endl;
    }

    return 0;
}
0