公式

D - Step Up Robot 解説 by en_translator


This problem has the following property:

  • Suppose that the robot is at the \(k\)-th step. Whether the robot can reach the \(l\)-th step is independent of the history of its move so far.

(For example, if the problem were like: “you have cards with non-negative integers written on them, and you may discard card \(x\) to advance \(x\) steps, but you cannot step on the step with a trap,” then the property above no longer holds, because the history affects to the upcoming moves.)

With the property above, we may design a DP (Dynamic Programming) that stores “the current step” as the state.

Define the following DP array.

  • \(\operatorname{dp}[i]\coloneqq \) \(1\) if you can step on the \(i\)-th step, and \(0\) otherwise.

Then, \(\operatorname{dp}[i]\) can be computed based on the positions of traps, \(B _ i\), and whether the robot can step on the steps below, \(\operatorname{dp}[0],\operatorname{dp}[1],\ldots,\operatorname{dp}[i-1]\).

Specifically, you can compute them as follows:

\[ \operatorname{dp}[i]=\left\lbrace\begin{matrix}0&\quad&({}^\exists j.\ B _ j=i)\\\displaystyle\bigvee_j \operatorname{dp}[i-A_j]&&(\textrm{otherwise}).\end{matrix}\right. \]

In a natural language, “a step without a trap can be reached if \(A _ i\) steps below can be reached.”

Initially, you are on the \(0\)-th step, so \(\operatorname{dp}[0]=1\) 、\(\operatorname{dp}[-n]=0\ (n\gt0)\). Together with the equation above, we can find \(\operatorname{dp}\) in the increasing order of \(i\).

The following is a sample code.

#include <iostream>
#include <vector>

int main() {
    using namespace std;

    unsigned long N;
    cin >> N;
    vector<unsigned long> A(N);
    for (auto &&a : A)
        cin >> a;

    unsigned long M;
    cin >> M;
    vector<unsigned long> B(M);
    for (auto &&b : B)
        cin >> b;

    unsigned long X;
    cin >> X;
    // dp[i] := Is i-th step reachable?
    // available[i] := Does i-th step have a trap?
    vector<unsigned long> dp(X + 1), available(X + 1, 1);
    for (const auto b : B)
        available[b] = 0;

    // 0-th step is reachable
    dp[0] = 1;
    for (unsigned long i{1}; i <= X; ++i)
        if (!available[i])
            // Step with a trap is unreachable
            dp[i] = 0;
        else
            // Without a trap, the "or" of dp[i - a] is the answer
            for (const auto a : A)
                if (i >= a)
                    dp[i] |= dp[i - a];

    cout << (dp[X] ? "Yes" : "No") << endl;

    return 0;
}

投稿日時:
最終更新: