문제 url:
ACM 호텔
문제:
해당 문제는 가장 거리가 가까울 수록 먼저 배정하는 방식으로 진행되는데,
엘리베이터는 상관 없이 얼마나 엘리베이터와 가까운 방에 위치하는가가 우선순위로 꼽힌다.
즉, 1층이 되었든 2층이 되었든 1호가 2호방보다 좋다는 의미이다.
101 better than 102
201 better than 102
301 better than 102
이를 그림으로 그려보자.
해당 문제는 이런식으로 방배정이 이루어진다는 것을 알 수 있다.
문제가 어떤 것인지 알아봤으니, 로직에 대해서 알아보자.
우리는 층(H)가 6이고 방(W)가 12라고 가정했을 때,
6층이 꽉 차면 그 다음 호실(1번방 -> 2번방 .... -> 12번방)로 움직이는 규칙이 있다는 것을 알 수 있다.
이제 층은 N % H를 하면 쉽게 구할 수 있다.
왜?? 6층을 다 배정하고 나머지가 곧 다른 층이기 때문
ex) 10 % 6 = 4
-> 현재 그림에서 몇층에 있는지를 확인하면 바로 이해할 수 있을것이다.
다르게 5 % 6 = 5
한다면 5층에 머문다는 것을 알 수 있다.
N % H == 0
이 된다면? 즉 손님이 6명있고 6층까지 있다면?
그렇다면 6층에 머물어야 하는데, 6 % 6
을 하게되면 0이 되어. 0층에 머물게 된다.
바닥에 잘 수도 없고 그렇다. 이때는 H층에 머물도록 해줘야 한다는 것이다.
if(N % H == 0) {
System.out.print(H);
} else {
System.out.print(N % H);
}
윗 말을 코드로 짜면 이렇게 할 수 있다는 얘기이다.
그렇게 층을 구했으면 그 다음은 곱하기 100을 해줌으로
백의 자리로 만들어준다.
갑자기 왜 뜬금없이 100을 곱하지??.. 한다면 당장 위를 봐도 101호 , 504호
층은 백의 자리로 되어 있다. 그래서 100을 곱한다.
층을 구해봤으면 이제 호를 구해야 한다.
층을 구할 때는 N % H를 해서 구할 수 있었다.
그렇다면, 호를 어떻게 구할까??
위의 그림을 그대로 다시 가져왔다.
여기서 우리 X01에 대해서 알아보자(x는 층을 의미) 6명이 꽉 찰때까지는 01호다.
그런 다음 6명이 꽉찬 후 7명째부터는 02호로 되어 있다.
여기서 더 나아가서 만약 13명의 고객이 온다면??
x02호까지는 12명이 찰 수 있다. 그러면 13번 째 고객은 x03호에 머물게 될 것이다.
그렇다. 호는 N / H
: 몫으로 구할 수 있는 것이다.
그런데, 만약 손님이 5명이 온다면 5 / 6 = 0
몫이 0이다. 하지만 호는 1호를 배정해야 하기에 N / H + 1
이 맞는 코드가 될 것이다.
그렇지만. 꼭대기 층 즉, h에 머무는 사람은 몫이 호에 맞게 떨어질 것이다.
즉, 6 / 6 = 1 , 12 / 6 = 2 이런식으로 말이다.
그렇게 되면 아까 이전에 1을 더하면 로직이 맞지 않다.
그래서 이를 코드화 하면
// 나머지가 0 즉, 꼭대기 층일때
if(N % H ==0) {
System.out.println(N / H);
// 꼭대기 층이 아닐때
} else {
System.out.println((N / H) + 1);
}
이런식으로 나타낼 수 있다. 이제 전체 코드를 보면서 이해해보자
import java.io.*;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sbd = new StringBuilder();
int tc = Integer.parseInt(br.readLine());
for (int i = 0; i < tc; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int H = Integer.parseInt(st.nextToken()); // 호텔의 층
int W = Integer.parseInt(st.nextToken()); // 각 층의 방 개수
int N = Integer.parseInt(st.nextToken()); // 몇 번째 고객
if(N % H == 0) {
sbd.append((H * 100) + (N / H)).append("\n");
} else {
sbd.append((N % H) * 100 + ((N / H) + 1)).append("\n");
}
}
System.out.println(sbd);
}
}
이렇게 나타낼 수 있다. 위의 설명을 읽으면 해당 코드를 이해하는데 문제 없을 것이라 생각한다.
여기서 W(방의 개수)는 안쓰는가? 쓰지 않는다. 아니 쓸 일이 없다.
이 문제를 풀 때 for문으로 하나씩 계산하여 for문때 작성하는 i변수, j변수로 호와 층을 계산하는 방법과 현재 풀었던 방식 이렇게 총 두개를 생각해봤었다.
그렇지만, 지금까지 코드리팩토링을 해오면서 불필요한 for문은 줄이면 좋다는 것을 배워왔기에 계산으로 바로 나오는 방법을 채택했다.
하지만! 역시 문제는 쉽게 풀리지 않았다.
import java.io.*;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sbd = new StringBuilder();
int tc = Integer.parseInt(br.readLine());
for (int i = 0; i < tc; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int H = Integer.parseInt(st.nextToken()); // 호텔의 층
int W = Integer.parseInt(st.nextToken()); // 각 층의 방 개수
int N = Integer.parseInt(st.nextToken()); // 몇 번째 고객
if(N % H == 0) {
sbd.append(H);
} else {
sbd.append(N % H);
}
if (N % H != 0 && N / H < 10) {
sbd.append(0).append((N / H) + 1).append("\n");
} else if(N % H == 0 && N / H < 10) {
sbd.append(0).append(N / H).append("\n");
} else if(N % H != 0 && N / H >= 10) {
sbd.append((N / H) + 1).append("\n");
} else {
sbd.append(N / H).append("\n");
}
}
System.out.println(sbd);
}
}
위는 초기에 짯던 코드이다.
처음에는 나머지(층)이 0이 되는 예외를 하지 않아 틀렸었고,
나는 문자열로 진행했기 때문에 10미만은 0을 붙여줘야 하는 예외도 처리해줬어야 했다.
그렇게 몇번의 시행착오 끝에! 했는데...
어랍쇼 문제가 계속 오답이다... 그래서 우리의 친구 지피티한테 물어봤는데
마지막 코드와, 초기 코드와 동일한 동작을 한다고 설명을 한다..
그럼 맞는거 아냐? 어후 멘탈과 시간이 너무 나갔었다 해당 문제를 풀면서
혹시 왜 이 코드가 안되는 건지 아시는 분이 계신다면 꼭 알려주시면 감사하겠습니다.
어쨋든.. 이렇게 문제를 풀고 예외처리를 진행하면서 트러블슈팅을 경험해볼 수 있었다.