티스토리 뷰

[BOJ 1328] 고층 빌딩

[BOJ 8895] 막대 배치 (위 문제와 거의 비슷함)


4일, 시간으로 따지면 7시간 정도 고민한 문제인데 풀릴 듯 안 풀려서 솔루션을 찾아보았다. dp테이블의 의미까지는 dp[n][l][r]=a n번째 막대까지 왼쪽에서 봤을 때 l개, 오른쪽에서 봤을 때 r개일때 가능한 경우의 수 a가지 까지는 똑같이 생각했으나 나머지 점화식을 떠올리지 못했다. 풀이의 핵심은 막대의 길이를 내림차순(긴 막대 -> 짧은 막대)으로 본다는 것이었다. 

만약 현재 dp[i][l][r]의 테이블을 채우기 위해서는 이전 막대의 l과 r이 1 작은 값의 경우의 수와 일치한다는 것이다. 이게 가능한 이유는 막대를 내림차순으로 사용하기 때문에, 현재 사용한 막대는 반드시 이전 막대들보다 짧다는 확신이 있기 때문이다. 그래서 현재 막대를 맨 왼쪽에 배치한다면 왼쪽에서 보이는 막대가 1개 늘어나게 되고 오른쪽의 경우도 마찬가지이다. 또한 현재 막대들 사이에 놓는 경우도 고려해야 하는데 이 역시 현재 막대는 다른 막대보다 짧다는 확신이 있기 때문에 l,r값에는 영향이 없고 그렇게 배치할 수 있는 경우의 수는 총(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
#include<stdio.h>
#define MOD 1000000007
typedef long long ll;
ll dp[111][111][111];
 
int main(){
    int n,l,r;    scanf("%d %d %d",&n,&l,&r);
 
    dp[1][1][1]=1;
    dp[2][1][2]=1,dp[2][2][1]=1;
 
    for(int i=3 ; i<=n ; i++){
        for(int lll=1 ; lll<=i ; lll++){
            for(int rrr=1 ; rrr<=i ; rrr++){
                dp[i][lll][rrr]+=dp[i-1][lll-1][rrr];
                dp[i][lll][rrr]+=dp[i-1][lll][rrr-1];
                dp[i][lll][rrr]+=dp[i-1][lll][rrr]*(i-2);
 
                dp[i][lll][rrr]%=MOD;
            }
        }
    }
 
    printf("%lld\n",dp[n][l][r]);
    return 0;
}
cs



'Problem Solving > Dynamic Programming' 카테고리의 다른 글

[BOJ 11062] 카드 게임  (0) 2019.01.29
[BOJ 1695] 팰린드롬 만들기  (0) 2019.01.23
[BOJ 2281]데스노트  (0) 2019.01.18
[BOJ 2568]전깃줄-2  (0) 2019.01.17
[BOJ 2662]기업투자  (0) 2019.01.16
댓글