백준 15787 - 기차가 어둠을 헤치고 은하수를
Updated:
Java
15787 번 - 기차가 어둠을 헤치고 은하수를
문제
접근 방법
기차의 수 N(1 ≤ N ≤ 100000)과 명령의 수 M(1 ≤ M ≤ 100000)는 보기와 같이 100000으로 큰 숫자이다.
따라서, 최대한 O(n)으로 해결하기 위해 2차원 배열을 이용해 기차를 나타내었고 기차 중복은 Set
을 이용하여 중복이 되지 않은 기차의 수를 세어 해결하였다.
코드
import java.util.*;
import java.io.*;
public class Main {
static int n, m, result;
static int[][] train;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
m = stoi(stk.nextToken());
train = new int[n + 1][20];
int order, tidx, idx;
while(m-- != 0) {
stk = new StringTokenizer(br.readLine());
order = stoi(stk.nextToken());
if(order == 1 || order == 2) {
tidx = stoi(stk.nextToken());
idx = stoi(stk.nextToken()) - 1;
if(order == 1)
train[tidx][idx] = 1; // 좌석 추가
else
train[tidx][idx] = 0; // 좌석 제거
}
else {
tidx = stoi(stk.nextToken());
if(order == 3)
back(tidx); // 좌석 뒤로 이동
else
front(tidx); // 좌석 앞으로 이동
}
}
Set<String> set = new HashSet<>();
for(int i = 1; i < n + 1; i++) {
set.add(Arrays.toString(train[i])); // set으로 중복 제거
}
System.out.println(set.size());
br.close();
}
static void front(int tidx) {
for(int i = 0; i < 19; i++) {
train[tidx][i] = train[tidx][i + 1];
}
train[tidx][19] = 0;
}
static void back(int tidx) {
for(int i = 19; i > 0; i--) {
train[tidx][i] = train[tidx][i - 1];
}
train[tidx][0] = 0;
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
비트 마스킹으로 해결
import java.util.*;
import java.io.*;
public class Main {
static int n, m, result;
static int[] train;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
m = stoi(stk.nextToken());
train = new int[n + 1];
int order, tidx, idx;
while(m-- != 0) {
stk = new StringTokenizer(br.readLine());
order = stoi(stk.nextToken());
if(order == 1 || order == 2) {
tidx = stoi(stk.nextToken());
idx = stoi(stk.nextToken()) - 1;
if(order == 1) {
train[tidx] |= 1 << idx; // 해당하는 좌석 등록
}
else {
train[tidx] &= ~(1 << idx); // 해당하는 좌석 삭제
}
}
else {
tidx = stoi(stk.nextToken());
if(order == 3) {
train[tidx] = train[tidx] << 1; // 모든 좌석을 뒤로 한 칸씩 보낸다.
train[tidx] &= (1 << 20) - 1; // 뒤로 보내면 20번째 bit가 생기므로 0 ~ 19 까지 비트를 1과 & 해주어 없애준다.
}
else {
train[tidx] = train[tidx] >> 1; // 앞으로 보낸다. 원래 제일 앞에 있던 좌석은 자동적으로 제거된다.
}
}
}
Set<Integer> set = new HashSet<>();
for(int i = 1; i < n + 1; i++) {
set.add(train[i]);
}
System.out.println(set.size());
br.close();
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
총평
후기
비트 마스킹을 제대로 써본 문제.
다음에 혼자 해결 할 수 있도록 복습이 필요한 문제이다.