백준 1328번 고층 빌딩
< 백준 1328번 고층 빌딩 - 마포 코딩박 >
사용한 알고리즘: DP
일렬로 늘어선 N개의 빌딩을 왼쪽(Left), 오른쪽(Right)에서 본 결과를 입력으로 받고, 가능한 배열의 수를 찾는 문제였습니다. DP를 사용하여 해결하였습니다. 풀이를 바로 생각하기 어려운 문제였습니다.
문제풀이는 다음과 같습니다.
(1) N개의 빌딩이 있을때, Left=1&&Right=N 이거나 정반대의 경우, 가능한 배열 수는 1 ( 유일 ) 입니다.
(2) N 개의 빌딩 배열은 N-1 개의 빌딩 배열에서 오는 것을 생각합니다.
(3) N-1 개 빌딩 배열로 -> N 개 빌딩 배열을 만든다고 생각할 때,
큰 빌딩 1개를 추가한다고 생각하면 헷갈리므로,
" N-1 개의 빌딩의 높이를 1씩 높여준 뒤, 높이 1 의 제일 작은 빌딩을 추가한다 "
라고 생각합니다.
(4) 위의 생각에서, N-1 개의 빌딩에 작은빌딩 1개를 추가로 배열 할 수 있는 위치 수는 N개 입니다.
(5) N-1개의 빌딩 양 끝에 작은 빌딩을 세우면 Left+1 or Right+1 이 됩니다. ( 2자리)
이를 제외한 모든 위치에 작은빌딩을 추가하는 것은 Left와 Right 에 변화를 줄 수 없습니다. ( N-2 자리)
(6) 위의 생각을 제귀함수로 구현하고, 이 과정에서 dp 를 활용해 저장합니다. ( 16번째 줄: 이미 완성된 배열일 경우 return 으로 중복해서 확인하는걸 줄여줘야 시간내에 돌릴 수 있습니다. )
위의 빨간색으로 강조한 생각을 하는 것이 힘들었습니다.
사용한 알고리즘: DP
일렬로 늘어선 N개의 빌딩을 왼쪽(Left), 오른쪽(Right)에서 본 결과를 입력으로 받고, 가능한 배열의 수를 찾는 문제였습니다. DP를 사용하여 해결하였습니다. 풀이를 바로 생각하기 어려운 문제였습니다.
문제풀이는 다음과 같습니다.
(1) N개의 빌딩이 있을때, Left=1&&Right=N 이거나 정반대의 경우, 가능한 배열 수는 1 ( 유일 ) 입니다.
(2) N 개의 빌딩 배열은 N-1 개의 빌딩 배열에서 오는 것을 생각합니다.
(3) N-1 개 빌딩 배열로 -> N 개 빌딩 배열을 만든다고 생각할 때,
큰 빌딩 1개를 추가한다고 생각하면 헷갈리므로,
" N-1 개의 빌딩의 높이를 1씩 높여준 뒤, 높이 1 의 제일 작은 빌딩을 추가한다 "
라고 생각합니다.
(4) 위의 생각에서, N-1 개의 빌딩에 작은빌딩 1개를 추가로 배열 할 수 있는 위치 수는 N개 입니다.
(5) N-1개의 빌딩 양 끝에 작은 빌딩을 세우면 Left+1 or Right+1 이 됩니다. ( 2자리)
이를 제외한 모든 위치에 작은빌딩을 추가하는 것은 Left와 Right 에 변화를 줄 수 없습니다. ( N-2 자리)
(6) 위의 생각을 제귀함수로 구현하고, 이 과정에서 dp 를 활용해 저장합니다. ( 16번째 줄: 이미 완성된 배열일 경우 return 으로 중복해서 확인하는걸 줄여줘야 시간내에 돌릴 수 있습니다. )
위의 빨간색으로 강조한 생각을 하는 것이 힘들었습니다.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <bits/stdc++.h> | |
using namespace std; | |
// 작은 빌딩을 넣는다고 생각 | |
const int MOD = 1000000007; | |
const int MAX = 102; | |
typedef long long ll; | |
int N, L, R; | |
ll dp[MAX][MAX][MAX]; | |
ll CountingNum(int building, int Left, int Right){ | |
// 기저 | |
if((Left==1&&Right==building)||(Left==building&&Right==1)) return 1LL; | |
// 불가능한 경우 | |
if(building==0||Left==0||Right==0) return 0LL; | |
ll &ret = dp[building][Left][Right]; | |
// 이미 아는 값이면 return | |
if(ret!=-1) return ret; | |
// 넣을 수 있는 자리 | |
int place = building-2; | |
ret = (CountingNum(building-1,Left,Right)*place+CountingNum(building-1,Left-1,Right)+CountingNum(building-1,Left,Right-1))%MOD; | |
return ret; | |
} | |
int main(){ios_base::sync_with_stdio(false); cout.tie(NULL); cin.tie(NULL); | |
cin >> N >> L >> R; | |
memset(dp,-1,sizeof(dp)); | |
cout << CountingNum(N,L,R)%MOD << '\n'; | |
return 0; | |
} |
댓글
댓글 쓰기
긴 글 읽어주셔서 감사합니다.
궁금한게 있으시다면 댓글 달아주세요!