[백준 1011] Fly me to the Alpha Centauri (C#, C++) - soo:bak
작성일 :
문제 링크
1011번 - Fly me to the Alpha Centauri
설명
어떤 우주선이 k
만큼 이동하였다면, 그 다음에는 k - 1
, k
, k + 1
중 한 경우로만 이동할 수 있을 때,
입력으로 주어지는 현재 위치 x
에서 목표 위치 y
로 최소한의 횟수로 이동하는 경우를 구하는 문제입니다.
탐색을 활용하여 문제를 풀이할 수도 있지만,
시간 복잡도를 고려하였을 때 가장 효율적인 풀이 방법은 수학적 일반항을 구하여 풀이하는 것입니다.
문제의 조건에 따르면 우주선은 이전 이동거리의 -1
, 0
, +1
중 하나로 이동할 수 있습니다.
이 때, 최대한 효율적으로 이동하기 위한 방법은 이동 거리를 늘리는 부분
과 이동 거리를 줄이는 부분
을 나누고,
이동 거리를 늘리는 부분에서는 최대한으로 거리를 늘리고 , 이동 거리를 줄이는 부분에서는 최대한으로 거리를 줄이는 것입니다.
가장 처음에는 -1
, 0
, +1
중에서 +1
만이 적절한 선택이므로,
이동 거리를 1
에서부터 최대한 늘리는 경우는 1
- 2
- 3
- ...
- k
과 같은 경우입니다.
이 때, 총 이동거리는 1
+ 2
+ 3
+ ...
+ (k - 1)
+ k
이 되므로, 공차가 1
인 등차 수열을 이룹니다.
즉, 최대한 늘리는 경우에서의 총 이동거리는 k(k + 1)
/ 2
가 됩니다.
이동 거리를 줄이는 부분에 대해서는 문제의 요구 조건 중 마지막 이동 거리는 1
이어야 한다 는 조건을 확인해야 합니다.
따라서, 현재 위치 x
와 목표 위치 y
사이에서 이동 거리를 늘리는 부분
과 이동 거리를 줄이는 부분
을 적절한 위치에서 나누는 것이 중요합니다.
이런 특징을 이용하여, 현재 위치 x
와 목표 위치 y
사이의 거리를 d
로, 거리 d
의 제곱근을 n
으로 가정하였을 때,
문제의 이동 거리 제한이 -1
, 0
, +1
중 하나라는 조건에 따라, n
은 거리 d
를 위해 소모되는 이동 횟수의 근사치가 됩니다.
예를 들어, 거리가 1
, 4
, 9
, 16
인 경우를 생각해 보면, 이들은 각각 12, 22, 32, 42와 같이 제곱수입니다.
이 때, 문제의 조건에 따라 각 경우에 필요한 최소 이동 횟수는 각각 1
, 3
, 5
, 7
이 됩니다.
이 값들은 각각 (2
* 1
- 1
), (2
* 2
- 1
), (2
* 3
- 1
), (2
* 4
- 1
)로, 거리의 제곱근의 2
배에서 1
을 뺀 값과 일치합니다.
따라서, n
을 거리 d
에 대한 이동 횟수의 근사치 로 가정하고, 다음과 같은 경우로 나누어 봅니다.
이동을 시작할 때,
d
가 (n
*n
) 와 같을 때
- 이 경우, 이동 거리는
n * n
과 같습니다. - 즉, 거리가
d
이자n * n
인 위치에 도달하려면, 거리를 늘릴 때n - 1
번 이동하고, 거리를 줄일 때n
번 이동해야 합니다. - 따라서, 최소 이동 횟수는 (
2
*n
) -1
이 됩니다.
- 이 경우, 이동 거리는
d
가 (n * n
) 보다 크고 (n
*n
) +n
보다 작거나 같을 때
- 이 경우, 해당
d
의 범위에 도달하기 위해서는, 거리를 늘릴 때n
번 이동해야 하며, 거리를 줄일 때n
번 이동해야 합니다. - 따라서, 최소 이동 횟수는 (
2
*n
) 이 됩니다.
- 이 경우, 해당
d
가 (n
*n
) +n
보다 클 때- 이 경우, 해당
d
의 범위에 도달하기 위해서는, 거리를 늘릴 때n + 1
번 이동해야 하며, 거리를 줄일 때n
번 이동해야 합니다. - 따라서, 최소 이동 횟수는 (
2
*n
) +1
이 됩니다.
- 이 경우, 해당
Code
[ C# ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
namespace Solution {
class Program {
static void Main(string[] args) {
var cntCase = int.Parse(Console.ReadLine()!);
for (int c = 0; c < cntCase; c++) {
var input = Console.ReadLine()!.Split(' ');
var x = long.Parse(input[0]);
var y = long.Parse(input[1]);
var d = y - x;
var n = (long)Math.Sqrt(d);
if (n * n == d)
Console.WriteLine(2 * n - 1);
else if (d > n * n && d <= n * n + n)
Console.WriteLine(2 * n);
else
Console.WriteLine(2 * n + 1);
}
}
}
}
[ C++ ]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int cntCase; cin >> cntCase;
for (int c = 0; c < cntCase; c++) {
ll x, y; cin >> x >> y;
ll d = y - x;
ll n = sqrt(d);
if (n * n == d)
cout << 2 * n - 1 << "\n";
else if (d > n * n && d <= n * n + n)
cout << 2 * n << "\n";
else
cout << 2 * n + 1 << "\n";
}
return 0;
}