본문 바로가기

개발/DS&Algorithms

[백준] ACM 호텔_10250_자바

10250번 Java - ACM 호텔


이번 문제의 분류는 <기본 수학1>에 해당합니다.
아래 문제를 보면 어렵게 느껴질 수 있겠지만, 타문제에 비해 비교적 간단한 문제입니다.
하지만 저는 문제를 풀면서 많은 시행착오를 겪게 되었습니다. 😂😂
그래서 이렇게 정리합니다.

현재 진행하는 코딩테스트 스터디 CoP장 형인님께서 아이디어 도움을 주셨습니다.
그리고 ST_LAB 티스토리를 통해 풀이 방법을 이해했습니다.
출처 : [https://st-lab.tistory.com/77]
https://www.acmicpc.net/problem/10250

 

10250번: ACM 호텔

프로그램은 표준 입력에서 입력 데이터를 받는다. 프로그램의 입력은 T 개의 테스트 데이터로 이루어져 있는데 T 는 입력의 맨 첫 줄에 주어진다. 각 테스트 데이터는 한 행으로서 H, W, N, 세 정수

www.acmicpc.net


1. 문제

 

 

2. 예제

 


3. 풀이

스터디장 형인님께서 아래와 같은 팁을 말씀해주었습니다.

수학 문제를 풀 때는 예제 입력과 출력을 활용한다.

나누기의 몫, 나머지를 활용한다.

팁을 따라서 아이디어를 생각해보겠습니다.
예제 입력에 따라 H(호텔의 층수)는 6, W(각 층의 방 수)는 12, N(몇 번째 손님)은 10 이라고 가정합니다.
이에 출력은 402를 출력합니다.
문제를 이해해보면 아래와 같이 방을 배정하는 방식입니다.

예제 입력의 출력 모습

층수에 맞게 손님들이 XX1호인 열방향으로 배정되게 됩니다. 하지만 위 그림과 같이 층수보다 방문객 수가 많다면 2열에 행으로 넘어가게됩니다. 그리고 남은 만큼 채우게 되는데요. 여기서 나머지를 활용한 것임을 눈치챌 수 있습니다.
다시 말하면, 10을 6으로 나누게 되는 것입니다. 만약 층수가 10층이었다면, 방문객은 1001호에 배정되게 됩니다.
이는 10에서 10을 나누었을때 나머지가 0이기 때문입니다.
여기서 추가로 나머지가 있다는 것은 다음으로 호 수로 넘어갔다는 뜻이고, 결국 몫에서 +1이 되는 것입니다.

  Test1 Test2
H 6 30
W 12 50
N 10 72
N/H 1 2
N%H 4 12
출력 402 1203

위 표를 참고하면, 나머지는 층 수가 되고, 몫에서 +1 한 값이 호 수가 되는 것입니다.
이제 이것을 식으로 표현하겠습니다.

( N % H ) * 100 + ( ( N / H ) + 1 )


여기서 추가로 예외를 고려해야 합니다.
만약 N % H 가 0이라면 실제로는 가장 높은 층(즉, H)의 방을 배정 받아야 합니다.
하지만 위 식의 경우라면, 1의 자리 수만 남게 됩니다.
따라서 if문을 통해서 (N % H) == 0 으로 예외를 따로 만들어 줍니다.

* W(각 층의 방 수)는 언제 이용되는가?
만약 문제에서 호텔의 방 개수만큼 손님으 받는다. 라는 조건이 있다면 N을 HxW 이하로 제한해줘야 한다.
하지만 해당 문제에서는 별다른 조건이 없기 때문에 따로 사용하지는 않는다.

- 방법 1

Scanner 이용
import java.util.Scanner; public class Main { public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); int T = sc.nextInt(); // 테스트 회수 입력 for(int i=0; i<T; i++) { int H = sc.nextInt(); // 호텔의 층 수 입력 int W = sc.nextInt(); // 각 층 방 수 입력 int N = sc.nextInt(); // 몇 번째 손님인지 입력 if( N % H == 0) { //예외 System.out.println((H*100) + (N/H)); } else { System.out.println(((N % H) * 100) + ((N / H) + 1)); } } } }

- 방법 2

BufferedReader, StringBuilder, StringTokenizer 이용
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringBuilder sb = new StringBuilder(); // StringBuilder는 출력할 문자열들을 하나로 묶어주고, 마지막에 한 번에 출력해주는 것 int T = Integer.parseInt(br.readLine()); // 테이스 케이스 for(int i = 0; i<T; i++) { StringTokenizer st = new StringTokenizer(br.readLine()," "); int H = Integer.parseInt(st.nextToken()); st.nextToken(); // W는 사용이 안되기 때문에 따로 변수를 지정해주지 않는다. int N = Integer.parseInt(st.nextToken()); if(N % H == 0) { sb.append((H * 100) + (N / H)).append('\n'); } else { sb.append(((N % H) * 100)+((N/H) + 1)).append('\n'); } } System.out.print(sb); } }

1) SpringBuilder

  • 불변성을 가지는 String 문자열을 다룰 때 사용
  • 문자열 추가, 수정, 삭제 등의 연산이 빈번하게 발생하는 알고리즘에서 사용

-> String 클래스는 힙 메모리(Heap)에 많은 임시 가비지(Garbage)가 생성되게 합니다. 이에 힙메모리 부족으로 어플리케이션 성능에 치명적인 영향을 끼칠 수 있습니다.
-> 위 문제를 해결하기 위해 Java는 가변(mutable)성을 가지는 StringBuffer / StringBuilder 클래스를 도입합니다.
-> .append( ), .delete( ) 등의 API를 이용하여 동일 객체 내에서 문자열을 변경하는 것이 가능합니다.
-> 단, StringBuillder는 StringBuffer보다 수행속도는 빠르나, 단일쓰레드와 동기화를 고려하지 않습니다.
위 코드에서는 테스트마다 출력되는 내용을 한번에 출력하기 위해 SpringBuillder를 활용했습니다.


4. 결과

  • 제출 번호 38916148 : BufferedReader, StringBuilder, SpringTokenizer
  • 제출 번호 38916092 : Scanner
반응형