公式

F - Teleporter Takahashi 解説 by en_translator


First, let us consider the one-dimensional version:

  • Takahashi is initially at the coordinate \(s\) on a number line. How can he reach \(t\) by repeatedly choosing an \(x\) such that \(a\leq x\leq b\) and moving to the place symmetric to \(x\)?

When \(x\) is chosen, Takahashi moves from \(p\) to \(2x-p\). Since \(p\equiv2x-p\pmod2\), if \(s\not\equiv t\pmod2\), he can never travel from \(s\) to \(t\). Hereinafter, we assume that \(s\equiv t\pmod2\).

If \(a=b\), he can just move only to \(s\) or \(2a-s\). After an even number of moves, he is at \(s\), after an odd number of moves, he is at \(2a-s\).

If \(a\neq b\), successively choosing \(a\) and \(a+1\) leads him from \(p\to p+2\), and successively choosing \(p\to p-2\) leads him from \(p\to p-2\).
Since \(s\equiv t\pmod2\), he can travel from \(s\) to \(t\) with \(|s-t|\) moves.


Now get back to the two-dimensional version. It is necessary that \(s _ x\not\equiv t_x\pmod2\) or \(s _ y\equiv t _ y\pmod2\).

If \(a=b\) or \(c=d\), then the coordinates \(s\) and \(t\) determines the parity of the number of moves. If

  • \(a=b\) and \(t _ x\notin\{s _ x,2a-s _ x\}\);
  • \(c=d\) and \(t _ y\notin\{s _ y,2c-s _ y\}\);
  • \(a=b\) and \(c=d\) and \(t _ x=s _ x\) and \(t _ y = 2c-s _ y\); or
  • \(a=b\) and \(c=d\) and \(t _ x=2a-s _ x\) and \(t _ y = s _ y\),

then the answer is No.

If we can determine that the number of moves is even, the \(x\) coordinates are the same as or distant by \(2k\) If the \(x\) coordinate are distant by \(2k(\neq0)\), then \(a\lt b\). In this case, consecutively choosing \((a,c)\) and \((a+1,c)\) leads him from \((p _ x,p _ y)\to(p _ x+2,p _ y)\). Also, consecutively choosing \((a+1,c)\) and \((a,c)\) leads him from \((p _ x,p _ y)\to(p _ x-2,p _ y)\). Therefore, \(|s _ x-t _ x|\) operations makes his \(x\) coordinate equal to \(s _ x\) without changing his \(y\) coordinate.

Similarly, as for the \(y\) coordinate, repeating “\((a,c)\) and \((a,c+1)\)” or “\((a,c+1)\) and \((a,c)\)” makes his \(y\) coordinate equal to \(s _ y\) without changing his \(x\) coordinate.

It requires \(|s _ x-t _ x|+|s _ y+t _ y|\leq4\times10^5\lt10^6\) moves, which is small enough.

If we can determine that the number of moves is odd, applying a single move boils down the problem to the even-moves case. For example, if he chooses \((a,c)\), the total number of moves required is \(1+|(2a-s _ x)-t _ x|+|(2c-s _ y)-t _ y|\leq1+8\times10^5\lt10^6\), so the problem has been solved.

The process is summarized as follows:

  • If the parities of \(s _ x\) and \(t _ x\) or \(s _ y\) and \(t _ y\) do not match, then the answer is No.
  • The answer is No if:
    • \(a=b\) and \(t _ x\notin\{s _ x,2a-s _ x\}\);
    • \(c=d\) and \(t _ y\notin\{s _ y,2c-s _ y\}\);
    • \(a=b\) and \(c=d\) and \(t _ x=s _ x\) and \(t _ y = 2c-s _ y\); or
    • \(a=b\) and \(c=d\) and \(t _ x=2a-s _ x\) and \(t _ y = s _ y\).
  • Otherwise, the answer is Yes.
  • If \(a=b\) and \(t _ x=2a-s _ x\), or \(c=d\) and \(t _ y=2c-s _ y\), then choose \((a,c)\) to make a move.
  • If \(s _ x\neq t _ x\), then repeatedly choose \((a,c)\) and \((a+1,c)\), or \((a+1,c)\) and \((a,c)\).
  • If \(s _ y\neq t _ y\), then repeatedly choose \((a,c)\) and \((a,c+1)\), or \((a,c+1)\) and \((a,c)\).

Below is a sample code. In such a problem, it is a good idea to define a function that performs an operation and an output at the same time, because it may simplify the implementation.

(Bonus: we may find the shortest sequence of operations.)

#include <iostream>

int main() {
    using namespace std;

    long sx, sy, tx, ty, a, b, c, d;
    cin >> sx >> sy >> tx >> ty >> a >> b >> c >> d;

    // If the parities do not match, No
    if ((sx ^ tx) % 2 != 0 || (sy ^ ty) % 2 != 0) {
        cout << "No" << endl;
        return 0;
    }

    // possible_0 : Can he reach with even moves?
    // possible_1 : Can he reach with odd moves?
    bool possible_0{(a != b || sx == tx) && (c != d || sy == ty)};
    bool possible_1{(a != b || sx + tx == a + b) && (c != d || sy + ty == c + d)};

    // If both is infeasible, No
    if (!possible_0 && !possible_1) {
        cout << "No" << endl;
        return 0;
    }

    // Otherwise, it's possible
    cout << "Yes" << endl;

    // Performs the move
    const auto instruction{[&sx, &sy](long x, long y){
        cout << x << " " << y << endl;
        sx = 2 * x - sx;
        sy = 2 * y - sy;
    }};

    // If odd moves are required, move somehow first
    if (!possible_0) instruction(a, c);

    // Move "two-by-two" to get closer
    while (sx < tx) { // Increase x
        instruction(a, c);
        instruction(a + 1, c);
    }
    while (sx > tx) { // Decrease x
        instruction(a + 1, c);
        instruction(a, c);
    }
    while (sy < ty) { // Increase y
        instruction(a, c);
        instruction(a, c + 1);
    }
    while (sy > ty) { // Decrease y
        instruction(a, c + 1);
        instruction(a, c);
    }

    return 0;
}

投稿日時:
最終更新: