[백준 / BOJ] C++ 17071

#17071: 숨바꼭질 5

문제

https://www.acmicpc.net/problem/17071

#17071: 숨바꼭질 5

수빈은 남동생과 숨바꼭질을 하고 있다.
수빈은 현재 포인트 N(0 ≤ N ≤ 500,000)에 있고 남동생은 포인트 K(0 ≤ K ≤ 500,000)에 있다.
수빈은 걷거나 텔레포트할 수 있다.
수빈의 위치가 X라면

www.acmicpc.net

설명

수빈(간단히 누나)은 다른 숨바꼭질처럼 +1, -1 또는 ×2를 이동할 수 있으며 1초가 걸립니다.
대신 동생은 1초에 1칸, 2초에 2칸, … N초에 N칸을 움직인다.
따라서 BFS 알고리즘을 사용하여 해결할 수 있습니다.

첫 번째 접근 방식은 각각에 대해 BFS를 수행하고(남동생은 실제로 하나만 이동하지만) 타임스텝으로 이동하고 언니가 이동할 때마다 여동생의 위치에 도달할 수 있도록 하는 것이었습니다.
그러나 71%가 TLE를 받았습니다.
그것을 풀기 위해 질문게시판을 뒤져보니… 정말 좋은 규칙과 아이디어를 발견했습니다.

이것은 당신의 여동생이 지나간 곳을 다시 지나갈 수 있다는 것을 의미합니다.
사실 그런 생각을 했고, 위에 구현을 할 때도 나름 적용을 했다.
하지만 끝없이 왔다 갔다 하며 홀수 시간에 도착하면 항상 홀수 시간에 방문할 수 있고, 짝수일 때도 마찬가지다.
따라서 홀수시간의 최초도착시간과 짝수시간의 최초도착시간을 별도로 기록한다.

따라서 2D 배열은 (위치) (홀수/짝수)로 변환됩니다.
BFS는 위치와 시간을 쌍으로 큐잉하여 수행됩니다.
위치 ×2, -1 및 +1에 대해서는 시간을 홀수/짝수로 기록하고 방문하지 않았거나 더 짧은 시간에 도달할 수 있는 시간을 기록합니다.

여동생의 현지 시간을 검색하여 여동생이 있는 장소에 홀수/짝수로 도착한 시간을 여동생이 도착한 시간과 비교하고, 여동생이 나중에 도착한 경우에는 여동생의 도착시간이 출력됩니다.
그와 별개로 남동생의 시간이 1씩 가고 남동생이 이동하며 다시 비교과정을 반복한다.
찾지 못하면 -1을 반환합니다.

너무 어렵다.
. 정신력과 체력이 많이 소모된다.
.

잘못된 코드

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

int n, k, t = 0, flag = 0;
vector<int> visitedS(500001, 0), visitedB(500001, 0);
queue<int> qS, qB;

void bfsS() {
  int size = qS.size();
  while (size--) {
    int x = qS.front();
    qS.pop();
    vector<int> nxt{curr * 2, curr - 1, curr + 1};
    for (int next : nxt)
      if (next >= 0 && next <= 500000)
        if (visitedS(next) < t) {
          q.push(next);
          visitedS(next) = t;
        }
  }
}

void bfsB() {
  int x = qB.front();
  qB.pop();
  t++;
  if (x + t >= 0 && x + t <= 500000) {
    qB.push(x + t);
    visitedB(x + t) = visitedB(x) + 1;
  } else {
    flag = 1;
  }
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(NULL);
  cin >> n >> k;
  if (n == k) {
    cout << 0;
    return 0;
  }
  qS.push(n);
  qB.push(k);
  while (!
qB.empty()) { if (flag) { cout << -1; return 0; } bfsB(); bfsS(); int x = qB.front(); if (x == 0) break; if (visitedS(x) == visitedB(x)) { cout << visitedS(x); return 0; } } cout << -1; return 0; }

올바른 코드

#include <bits/stdc++.h>
using namespace std;
#define INF 1e9

int n, k;
vector<vector<int>> sister(500001, vector<int>(2, INF));
vector<int> brother(500001, 0);

void bfs() {
  queue<pair<int, int>> q;
  q.push({n, 0});
  sister(n)(0) = 0;
  while (!
q.empty()) { int curr = q.front().first; int time = q.front().second; q.pop(); vector<int> nxt{curr * 2, curr - 1, curr + 1}; for (int next : nxt) if (next >= 0 && next <= 500000) if (sister(next)((time + 1) % 2) > time + 1) { q.push({next, time + 1}); sister(next)((time + 1) % 2) = time + 1; } } } int main() { ios::sync_with_stdio(false); cin.tie(NULL); cin >> n >> k; bfs(); int step = 1; while (k < 500001) { if (sister(k)(brother(k) % 2) <= brother(k)) { cout << brother(k); return 0; } if (k + step < 500001) brother(k + step) = brother(k) + 1; k += step; step++; } cout << -1; return 0; }