728x90
728x90
아이디어
빌딩을 큰 것부터 놓는다고 해보자. 그러면 그 다음 빌딩을 놓는 경우는 크게 세가지로 나눌 수 있다.
1. 가장 왼쪽에 배치
2. 가장 오른쪽에 배치
3. 가운데 아무데나 배치
왼쪽에 놓을 경우 그저 왼쪽에서 볼 수 있는 빌딩의 수가 하나 늘어나는 것이므로
빌딩을 n개 놓을 때 왼쪽에서 l개 보고 오른쪽에서 r개 보는 경우 = 빌딩을 n - 1개 놓을 때 왼쪽에서 l - 1개 보고 오른쪽에서 r개 보는 경우가 성립함을 알 수 있다.
오른쪽도 마찬가지다.
중간에 배치하는 경우는 배치할 빌딩이 가장 작으므로 왼쪽이나 오른쪽에서 볼 수 있는 빌딩의 개수는 변하지 않는다.
즉 빌딩을 n개 놓을 때 왼쪽에서 l개 보고 오른쪽에서 r개 보는 경우 = 빌딩을 n - 1개 놓을 때 왼쪽에서 l개 보고 오른쪽에서 r개 보는 경우 * 빌딩 사이에 놓는 경우가 성립한다.
구현
앞서 이야기 한 세가지를 통해 경우의 수를 높은 빌딩부터 배치하는 방식으로 점화식을 정할 수 있음을 알 수 있다.
dp[i][j][k] = dp[i - 1][j - 1][k] + dp[i - 1][j][k - 1] + dp[i - 1][j][k] * (i - 2)
이 점화식을 구현하기만 하면 문제를 해결 할 수 있다.
전체 코드
더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
#include <iostream>
using namespace std;
using ll = long long;
static int mod = 1e9 + 7;
int n, l, r;
ll dp[101][101][101];
int main()
{
dp[1][1][1] = 1;
ios::sync_with_stdio(false); cin.tie(0);
cin >> n >> l >> r;
for (int i = 2; i <= n; ++i)
{
for (int j = min(i, l); j > 0; --j)
{
for (int k = min(i, r); k > 0; --k)
{
dp[i][j][k] = dp[i - 1][j - 1][k];
dp[i][j][k] += dp[i - 1][j][k - 1];
dp[i][j][k] %= mod;
dp[i][j][k] += dp[i - 1][j][k] * (i - 2);
dp[i][j][k] %= mod;
}
}
}
cout << dp[n][l][r];
}
|
cs |
728x90
728x90
'백준 > DP' 카테고리의 다른 글
[ICPC] 백준 4811 - 알약 (0) | 2020.11.30 |
---|---|
백준 2248 - 이진수 찾기 (0) | 2020.11.21 |
[KOI] 백준 1983 - 숫자 박스 (0) | 2020.11.15 |
백준 2176 - 합리적인 이동경로 (0) | 2020.11.14 |
백준 1750 - 서로소의 개수 (0) | 2020.11.08 |