Problem link: https://www.acmicpc.net/problem/17071
크게 어렵지 않게 풀었는데, 풀이까지 이르게 된 사고의 흐름이 나름 기억해둘만해서 조금은 자세히 기록한다.
아래는 풀이와는 무관한 사고의 흐름이다.
CACHE[i]: i에 도착하는 데 걸리는 최소 시간
과 같이).CACHE[i][s]: s초에 수빈이가 i에 있는 것이 가능한지의 여부
).문제를 푸는 아이디어는 아래와 같다.
수빈이가 n
초 후에 i
에 위치한다면, 자연스럽게 i+2
, i+4
, ..., i+짝수
초 후에도 i
에 위치할 수 있다.
따라서, 아래와 같이 visit을 관리하여 BFS를 수행해준다.
visit[i][x]: 짝수 초(x==0) 또는 홀수 초(x==1) 후에 i에 도달할 때 가장 빠른 도달 시간
BFS를 진행하므로 가장 빠른 도달시간을 구하는데에는 큰 어려움이 없다.
x
초 후에 둘이 i
에서 만난다는 사실은 x - visit[i][x % 2] mod 2 == 0
으로 표현해 줄 수 있다(단, x
>= visit[i][x % 2]
).
#include <iostream>
#include <algorithm>
#include <queue>
#include <utility>
using namespace std;
const int kMaxN = 500000;
int SUBIN;
int BROTHER;
int VISIT[kMaxN + 1][2];
void Bfs()
{
queue<pair<int, int> > q;
VISIT[SUBIN][0] = 0;
q.emplace(SUBIN, 0);
while (!q.empty())
{
int here = q.front().first;
int odd = q.front().second;
q.pop();
if (0 <= here - 1 && VISIT[here - 1][1 - odd] == -1)
{
VISIT[here - 1][1 - odd] = VISIT[here][odd] + 1;
q.emplace(here - 1, 1 - odd);
}
if (here + 1 <= kMaxN && VISIT[here + 1][1 - odd] == -1)
{
VISIT[here + 1][1 - odd] = VISIT[here][odd] + 1;
q.emplace(here + 1, 1 - odd);
}
if (here * 2 <= kMaxN && VISIT[here * 2][1 - odd] == -1)
{
VISIT[here * 2][1 - odd] = VISIT[here][odd] + 1;
q.emplace(here * 2, 1 - odd);
}
}
}
int Solve()
{
Bfs();
for (int sec = 0;; ++sec)
{
BROTHER += sec;
if (BROTHER > kMaxN)
{
return -1;
}
else if (VISIT[BROTHER][sec % 2] != -1 && VISIT[BROTHER][sec % 2] <= sec &&
(sec - VISIT[BROTHER][sec % 2]) % 2 == 0)
{
return sec;
}
}
}
int main(void)
{
// Initialize
for (int i = 0; i < kMaxN + 1; ++i)
{
VISIT[i][0] = -1;
VISIT[i][1] = -1;
}
// For Faster IO
ios_base::sync_with_stdio(false);
cout.tie(nullptr);
cin.tie(nullptr);
// Read Input
cin >> SUBIN >> BROTHER;
// Solve
cout << Solve() << '\n';
return 0;
}