[백준 27590] Sun and Moon (C#, C++) - soo:bak
작성일 :
문제 링크
설명
시뮬레이션과 구현을 주제로 하는 문제입니다.
문제의 목표는 다음 일식이 일어날 연도
를 구하는 것입니다.
문제의 조건에 따르면,
해와 달이 특정한 위치
에서 일직선으로 정렬되어야 일식을 관측할 수 있다고 합니다.
또한, 문제의 입력으로는 다음과 같은 정보들이 주어집니다.
태양이 몇 년 전에 '특정한 위치' 에 있었는 지
태양이 다시 그 위치로 돌아오는 데에 몇 년이 걸리는 지
달이 몇 년 전에 '특정한 위치' 에 있었는 지
달이 다시 그 위치로 돌아오는 데에 몇 년이 걸리는 지
따라서, 태양과 달이 특정한 위치
에 돌아오는 연도를 모두 구한 후,
태양과 달이 특정한 위치
에 돌아오는 가장 빠른 ‘같은 연도’ 를 구하면,
다음 일식이 일어날 연도를 알 수 있게 됩니다.
또한, 문제의 추가 조건에 5000 년
안에는 무조건 일식이 일어난다는 가정이 있습니다.
따라서 비교적 탐색할 범위가 작기 때문에,
태양과 달이 특정한 위치
에 돌아오는 연도에 대해서는 단순히 완전 탐색을 이용하여 탐색을 진행했습니다.
이어서 구해야 할 것은 다음과 같습니다.
- 태양이
특정한 위치
에 돌아오는 연도들과, 달이특정한 위치
에 돌아오는 연도들 중에서가장 빠르면서도 같은 연도
해당 값을 탐색하는 과정은 비교적 빠른 탐색이 가능하도록 Hash-table
을 사용하였습니다.
(C++
에서는 unordered_set
이 내부적으로 Hash-table
을 사용하며, C#
에서는 HashSet
이 내부적으로 Hash-table
을 사용합니다.)
물론, 이중 for 문
을 이용하여 탐색을 진행할 수도 있지만, 이런 경우 최악의 경우에서 시간 복잡도가 O(N^2)
가 됩니다.
하지만, Hash-table
을 사용하면 최악의 경우 O(N)
의 시간복잡도를,
평균적인 경우 O(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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
namespace Solution {
class Program {
public record YEARS(int lastCorrectPosYear, int backToCorrectPosYear);
const int SUN = 0,
MOON = 1;
public static void Main() {
var SunInput = Console.ReadLine()?.Split();
var MoonInput = Console.ReadLine()?.Split();
YEARS[] years = new YEARS[2] {
new YEARS(int.Parse(SunInput![0]), int.Parse(SunInput![1])),
new YEARS(int.Parse(MoonInput![0]), int.Parse(MoonInput![1]))
};
int nextSunEclipse = -years[SUN].lastCorrectPosYear + years[SUN].backToCorrectPosYear;
int nextMoonEclipse = -years[MOON].lastCorrectPosYear + years[MOON].backToCorrectPosYear;
List<int> sunEclipses = new List<int> {nextSunEclipse};
List<int> moonEclipses = new List<int> {nextMoonEclipse};
const int MAX_YEAR = 5000;
while (true) {
if (nextSunEclipse > MAX_YEAR && nextMoonEclipse > MAX_YEAR) break;
if (nextSunEclipse <= MAX_YEAR) {
nextSunEclipse += years[SUN].backToCorrectPosYear;
sunEclipses.Add(nextSunEclipse);
}
if (nextMoonEclipse <= MAX_YEAR) {
nextMoonEclipse += years[MOON].backToCorrectPosYear;
moonEclipses.Add(nextMoonEclipse);
}
}
HashSet<int> sunHashSet = new HashSet<int>(sunEclipses);
foreach (int element in moonEclipses) {
if (sunHashSet.Contains(element)) {
Console.WriteLine(element);
break;
}
}
}
}
}
[ 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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <bits/stdc++.h>
using namespace std;
constexpr int SUN = 0;
constexpr int MOON = 1;
struct YEARS {
int lsatCorrectPosYear,
backToCorrectPosYear;
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
YEARS years[2];
cin >> years[SUN].lsatCorrectPosYear >> years[SUN].backToCorrectPosYear;
cin >> years[MOON].lsatCorrectPosYear >> years[MOON].backToCorrectPosYear;
int nextSunEclipse = -years[SUN].lsatCorrectPosYear + years[SUN].backToCorrectPosYear,
nextMoonEclipse = -years[MOON].lsatCorrectPosYear + years[MOON].backToCorrectPosYear;
vector<int> sunEclipses, moonEclipses;
sunEclipses.push_back(nextSunEclipse);
moonEclipses.push_back(nextMoonEclipse);
const int MAX_YEAR = 5000;
while (true) {
if (nextSunEclipse > MAX_YEAR && nextMoonEclipse > MAX_YEAR) break ;
if (nextSunEclipse <= MAX_YEAR) {
nextSunEclipse += years[SUN].backToCorrectPosYear;
sunEclipses.push_back(nextSunEclipse);
}
if (nextMoonEclipse <= MAX_YEAR) {
nextMoonEclipse += years[MOON].backToCorrectPosYear;
moonEclipses.push_back(nextMoonEclipse);
}
}
unordered_set<int> sunSet(sunEclipses.begin(), sunEclipses.end());
for (auto& element : moonEclipses) {
if (sunSet.find(element) != sunSet.end()) {
cout << element << "\n";
break ;
}
}
return 0;
}