백준 9095 [go]
문제
문제
정수 4를 1, 2, 3의 합으로 나타내는 방법은 총 7가지가 있다. 합을 나타낼 때는 수를 1개 이상 사용해야 한다.
1+1+1+1
1+1+2
1+2+1
2+1+1
2+2
1+3
3+1
정수 n이 주어졌을 때, n을 1, 2, 3의 합으로 나타내는 방법의 수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스는 한 줄로 이루어져 있고, 정수 n이 주어진다. n은 양수이며 11보다 작다.
출력
각 테스트 케이스마다, n을 1, 2, 3의 합으로 나타내는 방법의 수를 출력한다.
풀이
DP문제다.
우선 작은 숫자들부터 생각하면
| 숫자 | 더하는 방법 | 개수 |
| 1 | 1 | 1 |
| 2 | 1+1, 2 | 2 |
| 3 | 1+1+1, 1+2, 2+1, 3 | 4 |
4부터는
3+1, 2+1+1, 1+2+1, 1+1+1+1
2+2, 1+1+2
1+3
7가지다.
살펴보면 마지막 숫자를 고정해놓고, 첫째줄은 마지막 숫자가 1로, 3에다 1을 더하는 것을 풀어쓴거다.
즉, 3+1에서 3을 위 테이블에서 더하는 방법대로 쪼개서 쓴 것
둘째줄은 2에다 2를 더하는 것
마지막은 1에다 3을 더하는 것
5를 예시로 들면 4에 1을 더하고, 3에 2를 더하고, 2에 3을 더할 수 있다. 1에는 4가 와야하므로 안됨. 결과적으로 고정 숫자는 3까지 올 수 있으므로 이후에도 계속
(현재 숫자 경우의 수) = (현재숫자-1 경우의수) + (현재숫자-2 경우의 수) + (현재숫자-3 경우의 수) 가 될 것이다.
따라서 1부터 3까지를 미리 계산해 배열에 넣어놓고 이후는 저렇게 계산해서 넣어주면 된다.
코드로 쓰면 아래와 같다
// problem9095.go
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
var reader *bufio.Reader = bufio.NewReader(os.Stdin)
var writer *bufio.Writer = bufio.NewWriter(os.Stdout)
defer writer.Flush()
var t int
var d [20]int
d[1] = 1
d[2] = 2
d[3] = 4
for i := 4; i < 11; i++ {
d[i] = d[i-1] + d[i-2] + d[i-3]
}
fmt.Fscanln(reader, &t)
var n int
for i := 0; i < t; i++ {
fmt.Fscanln(reader, &n)
fmt.Fprintln(writer, d[n])
}
}

