본문 바로가기
Algorithm

백준 12101번 <1, 2, 3 더하기 2>

by seungh2 2020. 9. 2.

백준 알고리즘 12101번

https://www.acmicpc.net/problem/12101

 

12101번: 1, 2, 3 더하기 2

n을 1, 2, 3의 합으로 나타내는 방법 중에서 사전 순으로 k번째에 오는 것을 출력한다. k번째 오는 식이 없는 경우에는 -1을 출력한다.

www.acmicpc.net

9095번에서 발전된 문제

 

처음에는!!!!

2차원 배열을 사용해서 풀었다.

 

그런데 자꾸 런타임 에러가 나서 으으으음!!! 이러면서 ArrayList를 사용해서 풀었다.

(ArrayList 안의 원소는 LinkedList형이다.)

 

굳이라는 생각이 들었지만 혹시 2차원 배열에 빈 공간이 너무 많아서 그런가 하고 이렇게 풀었는데

 

알고 보니까 2차원 배열의 크기를 알맞지 않게 해서 런타임 에러가 뜬 거였다...

멍청해.... ㅠㅠ

 

굳이라고 생각이 드는 ArrayList가 아니라 2차원 배열을 사용한 것을 포스팅할 거다!!

(어차피 2차원 배열로 만드는 것을 ArrayList로 바꾼 것뿐이라 알고리즘은 딱히 다른 게 없다.)


12101번

입력으로 들어오는 정수 n(양수)과 k로

n을 1, 2, 3의 합으로 나타내는 방법 중에서 사전 순으로 k번째에 오는 것을 출력해준다.

만약 k번째 오는 식이 없는 경우에는 -1을 출력한다.


문제 해결

일단 answer이라는 int형 2차원 배열을 생성했다.

 

백준 알고리즘 9095번에서 보면 10일 때 1, 2, 3의 합으로 나타내는 방법의 수는 274이다.

 

그래서 2차원 배열을 new int[11][275]로 생성했다.

-> 입력으로 주어지는 n이 11보다 작으니까 n의 최댓값은 10이다. 

     0은 빼고 1부터 10까지 하려고 11로 해주었다.

-> 입력으로 주어지는 k가 0이 아니라 1부터 시작하기 때문에 

    배열의 크기를 274가 아니라 274+1인 275로 해주었다. (이거 때문에 런타임 에러 뜸...)

 

1. answer[N][0]에는 N을 1, 2, 3의 합으로 나타내는 방법의 수를 구해서 저장한다.

   (9095번의 코드를 이용해서 구한다.)

 

2. 만약 answer[n][0]의 값이 k보다 작으면 = k번째 오는 식이 없다.

   -1을 출력한다.

 

3. 2번의 조건을 만족하지 않으면

   9095번의 코드를 활용해서 2차원 배열을 채워준다.

 

2차원 배열 채워주기.

answer[1][0]은 1로, answer [1][1]은 "1"로 미리 채운다.

 

for문을 2부터 n까지 돌린다. (for문의 변수를 i라고 했을 때)

i - 1 은 1+### 이런 형식으로 사전 순에서 처음 부분

i - 2 는 2+### 이런 형식으로 사전 순에서 중간 부분

i - 3 는 3+### 이런 형식으로 사전 순에서 끝 부분

 

for문 안에서는 i가 2, 3일 때는 예외처리를 해주어야 한다.

(i가 2면 i-2와 i-3 부분을 할 필요가 없고 i가 3일 때는 i-3부분을 할 필요가 없기 때문에)

 

만약 i가 4라면 

i - 1 = 3으로 1 + (3을 1, 2, 3의 합으로 나타내는 방법)을 차례대로 구해서 배열에 넣어주면 된다.

3을 1, 2, 3의 합으로 나타내는 방법들은 answer[3]에 저장되어 있다.

answer[3][0]으로 3을 1, 2, 3의 합으로 나타내는 방법의 수를 알 수 있으니까 그만큼 for문을 돌려서

answer[4][1] = 1+answer[3][1]

answer[4][2] = 1+answer[3][2]

answer[4][3] = 1+answer[3][3]

answer[4][4] = 1+answer[3][4]

이렇게 넣어주면 된다.

 

i - 2 = 2 으로 2 + (2를 1, 2, 3의 합으로 나타내는 방법)을 차례대로 구해서 배열에 넣어주면 된다.

2를 1, 2, 3의 합으로 나타내는 방법들은 answer[2]에 저장되어 있다.

answer[2][0]으로 2를 1, 2, 3의 합으로 나타내는 방법의 수를 알 수 있으니까 그만큼 for문을 돌려서

answer[4][answer[3][0]+1] = 2+answer[2][1]

answer[4][answer[3][0]+2] = 2+answer[2][2]

이렇게 넣어주면 된다.

 

i - 3 = 1으로 3 + (1를 1, 2, 3의 합으로 나타내는 방법)을 차례대로 구해서 배열에 넣어주면 된다.

1를 1, 2, 3의 합으로 나타내는 방법들은 answer[1]에 저장되어 있다.

answer[1][0]으로 2를 1, 2, 3의 합으로 나타내는 방법의 수를 알 수 있으니까 그만큼 for문을 돌려서

answer[4][answer[3][0]+answer[2][0]+1] = 3+answer[1][1]

이렇게 넣어주면 된다.

 

위에 구하는 법을 표로 나타내 보면 아래와 같다.

파란 글씨는 1, 2, 3의 합으로 나타내는 방법의 수를 나타내고

핑크 화살표를 따라가면 어디서 나타난 숫자들인지 알 수 있다.


코드

import java.io.IOException;
import java.util.Scanner;

public class Main {

	public static void main(String[] args) throws IOException {

		Scanner sc = new Scanner(System.in);

		int num = sc.nextInt();
		int k = sc.nextInt();


		String[][] answer = new String[11][275];
		answer[1][0] = "1";

		for (int i = 2; i < (num + 1); i++) {
			int sub = i - 1;
			int result = Integer.parseInt(answer[sub][0]);

			if (sub == 1) {
				result++;
				answer[i][0] = String.valueOf(result);
				continue;
			}

			sub = i - 2;
			result += Integer.parseInt(answer[sub][0]);

			if (sub == 1) {
				result++;
				answer[i][0] = String.valueOf(result);
				continue;
			}

			sub = i - 3;
			result += Integer.parseInt(answer[sub][0]);
			answer[i][0] = String.valueOf(result);

		}

		answer[1][1] = "1";

		int check = Integer.parseInt(answer[num][0]);
		if (check < k) {
			System.out.println("-1");
		} else {
			for (int i = 2; i < num + 1; i++) {
				int sub = i - 1;
				int size = Integer.parseInt(answer[sub][0]);

				for (int j = 1; j < size + 1; j++) {
					answer[i][j] = "1+" + answer[sub][j];
				}

				if (sub == 1) {
					answer[i][2] = "2";
					continue;
				}

				sub = i - 2;
				int newSize = Integer.parseInt(answer[sub][0]);

				for (int j = 1; j < newSize + 1; j++) {
					answer[i][j + size] = "2+" + answer[sub][j];
				}
				size += newSize;

				if (sub == 1) {
					answer[i][4] = "3";
					continue;
				}

				sub = i - 3;
				newSize = Integer.parseInt(answer[sub][0]);

				for (int j = 1; j < newSize + 1; j++) {
					answer[i][j + size] = "3+" + answer[sub][j];
				}
			}

			System.out.println(answer[num][k]);
		}

	}

}


728x90

'Algorithm' 카테고리의 다른 글

백준 11399번 <ATM>  (0) 2021.01.12
백준 11047번 <동전 0>  (0) 2021.01.09
백준 12865번 <평범한 배낭>  (0) 2020.09.01
백준 5177번 <출력 형식이 잘못 되었습니다.>  (0) 2020.08.31
백준 10926번 <??!>  (0) 2020.08.29

댓글