# 백준 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까지를 미리 계산해 배열에 넣어놓고 이후는 저렇게 계산해서 넣어주면 된다.

코드로 쓰면 아래와 같다

```go
// 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])
	}
}
```
