[동적 계획법] POLY 폴리오미노
2021. 1. 11. 11:43ㆍ알고리즘/알고리즘 문제 [medium]
1. 문제의 변형
n개의 정사각형으로 모든 경우의 도형을 만들 수 있는 수는
구하기가 까다롭다.
하지만 문제는 세로로 단조인 폴리오미노를 구하라는 것이므로
쉽게 문제를 변형하여 풀 수 있게된다.
세로로 단조인 폴리오미노는 가로의 직사각형으로만으로 모든
경우의 수를 구할 수 있음을 나타낸다.
즉, 이문제 는 탑쌓기로 변형할 수 있는데
1층에 몇개의 정사각형을 쓰는지
2층에 나머지 정사각형에서 몇개를 쓰는지
.
.
.
n층에 몇개를 쓰는지
결국 이문제는 재귀 호출로 문제를 풀 수 있게 된다.
2. 점화식
이 문제를 풀 점화식은
poly(remain, before) = remain만큼 정사각형이 남아있는 단계에서 before의 개수가 이전에 쓰인 경우의
세로 단조인 폴리오미노의 개수
move = 1 (before = 0)
move = before + i -1 (before < 0)
3. 코드
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
34
35
36
37
38
39
40
41
|
#include <iostream>
#include <vector>
#include <cstring>
const int MOD = 10*1000*1000;
int cache[101][101];
int poly(int remain , int before)
{
int &ret = cache[remain][before], move = 0;
if(ret != -1) return ret;
if(remain == 0) return 1;
ret = 0;
for(int i = remain; i >= 1; i--)
{
move = before + i - 1;
if(before == 0)
ret = (ret + poly(remain - i, i))%MOD;
else
ret = (ret + move * poly(remain - i, i))%MOD;
}
return ret;
}
int main(void)
{
int testCase = 0;
int n = 0;
memset(cache, -1, sizeof cache);
std::cin>>testCase;
for(int i = 0; i < testCase; i++)
{
std::cin>>n;
std::cout<<poly(n, 0)<<std::endl;
}
}
|
4. 반성
문제를 변형하는 방법을 책에서 읽지 않았더라면 하루안에 문제를 풀지 못햇을 것이다.
여러 측면에서 문제를 생각해야겠다.
'알고리즘 > 알고리즘 문제 [medium]' 카테고리의 다른 글
[동적 계획법][시간 초과] KLIS: K-th Longest Increasing Sequence (0) | 2021.01.14 |
---|---|
[동적 계획법] OCR 광학 문자 인식 (0) | 2021.01.13 |
[동적 계획법] ASYMTILING 비대칭 타일링 (0) | 2021.01.10 |
[동적 계획법, 그래프] JUMPGAME 외발 뛰기 (0) | 2021.01.06 |
[분할 정복] FANMEETING 팬미팅 (0) | 2021.01.05 |