https://www.acmicpc.net/problem/15989
15989번: 1, 2, 3 더하기 4
정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 4가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다. 합을 이루고 있는 수의 순서만 다른 것은 같은 것으로 친다. 1+1+1+1 2+1+1 (1+1+2, 1+2+1) 2+2
www.acmicpc.net
다이나믹 프로그래밍으로 점화식을 구해서 풀어야 하는 문제.
1차원 적으로 생각했다가 도저히 답이 안 나왔는데 dp 테이블을 2차원 배열로 나누어 풀어야지 풀 수 있었다.
dp[i][0] : i를 만들 때 1이 가장 앞에 오는 경우 ex) i=4 1+1+1+1
dp[i][1] : i를 만들 때 2가 가장 앞에 오는 경우 ex) 2+1, 2+2
dp[i][2] : i를 만들 때 3이 가장 앞에 오는 경우 ex) 3+1
위처럼 2차원으로 3가지 경우로 나누어서 생각해야 함.
점화식
- dp[i][0] = 1 맨 앞에 1이 오는 경우는 오직 1의 합으로 표현하는 경우 하나밖에 없다.
- dp[i][1] = dp[i-2][0] + dp[i-2][1] 맨 앞에 2가 오는 경우는 뒤에 3은 올 수 없으므로 제외하고 이미 2를 앞에 썼기 때문에 i에서 2를 뺀 수의 맨 앞에 1이 오는 경우, 2가 오는 경우를 더해주어야 한다.
- dp[i][2] = dp[i-3][0] + dp[i-3][1] + dp[i-3][2] 맨 앞에 3이 오는 경우는 이미 3을 앞에 썼기 때문에 i에서 3을 뺀 수의 맨 앞에 1,2,3이 오는 경우를 더해 준다.
위 점화식은 N>=4 일 때 기능한다. 따라서 N <4 일 때의 경우를 수기로 작성해 주자.
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
StringBuilder sb =new StringBuilder();
int T, number;
int[][] dp = new int[10001][3];
dp[1][0] = 1; //1로 시작해 1을 표현하는 방법 1
dp[2][0] = dp[2][1] = 1; //각각 1과 2로 시작해 2를 표현하는 방법 1+1, 2
dp[3][0] = dp[3][1] = dp[3][2] = 1; //각각 1,2,3으로 시작해 3을 표현하는 방법 1+1+1, 2+1, 3
for(int i=4; i<10001; i++){
dp[i][0] = 1;
dp[i][1] = dp[i-2][0] + dp[i-2][1];
dp[i][2] = dp[i-3][0] + dp[i-3][1] + dp[i-3][2];
}
T = Integer.parseInt(br.readLine());
for(int i=0; i<T; i++){
number = Integer.parseInt(br.readLine());
sb.append(dp[number][0]+dp[number][1]+dp[number][2]+"\n");
}
System.out.println(sb);
}
}
'알고리즘 문제 > 다이나믹 프로그래밍' 카테고리의 다른 글
[Java] 다이나믹 프로그래밍 (쉬운 계단 수) (0) | 2023.06.28 |
---|---|
[Java] 다이나믹 프로그래밍 (신나는 함수 실행) (0) | 2023.06.27 |
[Java] 다이나믹 프로그래밍 (진우의 달 여행 (Large)) (0) | 2023.02.16 |
[Java] 다이나믹 프로그래밍 누적 합 (구간 합 구하기5) (0) | 2023.02.01 |
[Java] 배낭 문제 (안녕) (0) | 2023.01.12 |