BOJ 1620 나는야 포켓몬 마스터 이다솜
나는야 포켓몬 마스터 이다솜 (https://www.acmicpc.net/problem/1620)
문제 분석
지문의 99%는 필요가 없다.
현재 가지고 있는 포켓몬 도감에서 포켓몬의 이름을 보면 포켓몬의 번호를 말하거나, 포켓몬의 번호를 보면 포켓몬의 이름을 말하는 연습을 하도록 하여라.
분석 끝
접근
포켓몬의 수와 문제의 수가 최대 10만개이다. STL VS COLLECTION 시리즈 1편에서 설명한것처럼 배열스타일로 이 문제를 풀면, 가장 끝에 있는 포켓몬을 10만번 출력 시키라고 하면 인생이 망하는 것이다. 검색과정에 O(logN)의 시간복잡도를 가지는 TreeMap을 사용함으로써 최대 10만+log2(10만) 의 연산량으로 답을 내도록 하자. 이 문제는 그냥 맵의 사용만 유도하는 문제라 사실 TreeMap일 필요가 없다. 해시맵으로도 가능하고, 해시 충돌이 없을경우 훨씬 빠르다.
1. 이름을 받아 맵에 저장
map<string, int> simap;
for (int i = 1; i <= n; ++i) {
cin >> str;
simap[str] = i;
}
입력되는대로 1번 2번… 순이라고 하였으니 위와 같이 셋팅한다.
2. 쿼리
이후의 M개의 줄에
입력으로 숫자가 들어왔다면 그 숫자에 해당하는 포켓몬의 이름을, 문자가 들어왔으면 그 포켓몬의 이름에 해당하는 번호를 출력하면 돼. 라고 한다.
우리는 맵에 string:int 쌍을 저장했기 때문에 이름을 물어봤을때 번호를 답해주기는 쉽다.
cin >> str;
if (s[0] < '0' && '9' < s[0]) { // 첫 글자가 숫자 범위가 아니면
cout << simap[str] << '\n';
}
그런데 번호를 물어봤을때 이름을 답하는 과정은 어떻게 처리할까? 지금대로라면 int:string 쌍의 정보도 없고 트리맵의 구조상 value로 find를 할 수가 없다.
그러므로 처음 입력받을때 int:string인 맵도 같이 만들어주자.
map<string, int> simap;
map<int, string> ismap;
for (int i = 1; i <= n; ++i) {
cin >> str;
simap[str] = i;
ismap[i] = str;
}
마치 양방향 그래프 같은 느낌이다. 이렇게 하면 우리는 이제 번호를 물어봤을 때 포켓몬의 이름 대답도 할 수 있게 되었다.
cin >> str;
if (s[0] < '0' && '9' < s[0]) { // 첫 글자가 숫자 범위가 아니면
cout << simap[str] << '\n';
}
else { // 첫 글자가 숫자 범위이면
cout << ismap[stoi(str)] << '\n';
}
C++ 소스
#include<iostream>
#include<map>
#include<string>
using namespace std;
int n, m;
string str;
map<string, int>simap;
map<int, string>ismap;
int main() {
cin.sync_with_stdio(0); cin.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; ++i) {
cin >> str;
simap[str] = i;
ismap[i] = str;
}
while (m--) {
cin >> str;
if (str[0] < '0' || str[0] > '9') { // 첫 글자가 숫자 범위가 아니면
cout << simap[str] << '\n';
}
else { // 첫 글자가 숫자 범위이면
cout << ismap[stoi(str)] << '\n';
}
}
}
Java 소스
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
StringBuilder sb = new StringBuilder();
int n = Integer.parseInt(st.nextToken());
int m = Integer.parseInt(st.nextToken());
Map<String, Integer> simap = new TreeMap<>();
Map<Integer, String> ismap = new TreeMap<>();
for (int i = 1; i <= n; ++i) {
String str = br.readLine();
simap.put(str, i);
ismap.put(i, str);
}
for (int i = 0; i < m; ++i) {
String str = br.readLine();
if (str.charAt(0) < '0' || str.charAt(0) > '9') { // 첫 글자가 숫자 범위가 아니면
sb.append(simap.get(str));
} else { // 첫 글자가 숫자 범위이면
sb.append(ismap.get(Integer.parseInt(str)));
}
sb.append("\n");
}
System.out.println(sb);
}
}