IT 기획의 길
백준 15990번 1,2,3 더하기 5 [JAVA] 본문
문제
정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 3가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다. 단, 같은 수를 두 번 이상 연속해서 사용하면 안 된다.
- 1+2+1
- 1+3
- 3+1
정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 100,000보다 작거나 같다.
출력
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 1,000,000,009로 나눈 나머지를 출력한다.
이 문제는 어려워서 어제 풀다가 포기한 문제였다
쉬운 계단수, 이친수 문제를 풀고 오니까 좀 수월졌지만 처음에는 진짜 감을 잡지 못하였다
알고리즘 설계
1. long [][]dp=new long[end][4]인 배열을 선언한다 (end=100001)
행은 1~1000000까지의 수가 오는 자리
열은 1,2,3 즉 마지막으로 더한수에 대한 정보이다
ex) dp[20][3] -> 1,2,3의 합으로 20이 된 경우의 수중에 마지막으로 3을 더해서 20이 된 경우의 수
2. 점화식을 만든다
dp[i][1] -> 숫자 i를 1,2,3의 합으로 나타낼수 있는 경우의 수 중에 마지막수를 1로 더한 경우
()+1=i가 된다
()부분은 dp[i-1][2]+dp[i-1][3]이 된다
()부분은 숫자 i-1를 1,2,3의 합으로 나타낼수 있는 경우의 수중에 마지막수를 2,3으로 더한 경우
dp[i][2] -> 숫자 i를 1,2,3의 합으로 나타낼수 있는 경우의 수 중에 마지막수를 2로 더한 경우
()+2=i가 된다
()부분은 dp[i-2][1]+dp[i-2][3]이 된다
()부분은 숫자 i-2를 1,2,3의 합으로 나타낼수 있는 경우의 수중에 마지막수를 1,3으로 더한 경우
dp[i][3] -> 숫자 i를 1,2,3의 합으로 나타낼수 있는 경우의 수 중에 마지막수를 3으로 더한 경우
()+3=i가 된다
()부분은 dp[i-3][1]+dp[i-3][2]이 된다
()부분은 숫자 i-3를 1,2,3의 합으로 나타낼수 있는 경우의 수중에 마지막수를 1,2으로 더한 경우
단
dp[i][1]을 구하는 점화식의 경우 i>1이여야 한다 마지막수로 1을 더해서 생긴 수가 1보다 작거나 같을수는 없으니까
dp[i][2]을 구하는 점화식의 경우 i>2이여야 한다 마지막수로 2를 더해서 생긴 수가 2보다 작거나 같을수는 없으니까
dp[i][3]을 구하는 점화식의 경우 i>3이여야 한다 마지막수로 3을 더해서 생긴 수가 3보다 작거나 같을수는 없으니까
그래서 1~3까지의 수는 미리 초기화 시켜놓고 풀었다.
3. 문제에서 요구하는대로 1000000009로 나눠준다
1000000009으로 나눈 값이 저장될 배열이니까 dp배열을 long형으로 선언해준것이다
import java.util.*;
public class Main {
public static void main(String[] args){
Scanner sc=new Scanner(System.in);
long mod= 1000000009;
int end=100001;
long [][]dp=new long[end][4];
// 1,2,3에 의해 i<4인 경우는 미리 초기화 시켜놓는다
dp[1][1]=1;
dp[1][2]=0;
dp[1][3]=0;
dp[2][1]=0;
dp[2][2]=1;
dp[2][3]=0;
dp[3][1]=1;
dp[3][2]=1;
dp[3][3]=1;
for(int i=4;i<end;i++){
for(int j=1;j<=3;j++){
if(j==1 ){ //1. i>1
dp[i][1]=(dp[i-1][2]+dp[i-1][3])%mod;
}
else if(j==2 ){ //2. i>2
dp[i][2]=(dp[i-2][1]+dp[i-2][3])%mod;
}
else if(j==3 ){ //3. i>3
dp[i][3]=(dp[i-3][1]+dp[i-3][2])%mod;
}
}
}
int t=sc.nextInt();
for(int i=0;i<t;i++){
int n=sc.nextInt();
System.out.println((dp[n][1]+dp[n][2]+dp[n][3])%mod);
}
}
}
'알고리즘(백준) > DP' 카테고리의 다른 글
백준 1699번 제곱수의 합 [JAVA] (0) | 2021.01.12 |
---|---|
백준 1912번 연속합 [JAVA] (0) | 2021.01.12 |
백준 2193번 이친수 [JAVA] (0) | 2021.01.11 |
백준 10844번 쉬운 계단 수 [JAVA] (0) | 2021.01.11 |
백준 11052번 카드 구매하기 [JAVA] (0) | 2021.01.10 |