KoreanFoodie's Study
[종만북 문제] 폴리오미노 (문제 ID : POLY, 난이도 : 중) 본문
프로그래밍 대회에서 배우는 알고리즘 문제해결 전략(이하 종만북)에서 소개된 문제를 풀이합니다. 알고리즘에 진심이시라면, 직접 구매하셔서 읽어보시는 것을 추천합니다!
핵심 :
1. 언뜻 불가능해 보이는 문제도, 문제의 조건을 잘 보면 부분 문제의 조합으로 분해해 볼 수 있다!
[종만북 문제] 폴리오미노 (문제 ID : POLY, 난이도 : 중)
휴.. 맨 처음에는 무슨 문제인가 싶었지만, 결국 풀어내서 성취감이 있는 문제였다.
책에 있는 접근법을 조금 가져와 보자면...
위의 성질을 이용해서 점화식을 세우면 된다. 왜 이렇게 되냐면, 한 줄에 있는 블럭들은 서로 떨어져 있으면 안되고 붙어 있어야 하는 성질 때문이다! 😉
점화식은 대략 아래처럼 생겼다.
나 같은 경우, 처음에는 아래처럼 for-loop 으로 풀었었다. (추후 보기 편하라고 변수 명을 first, second 로 바꿈)
#include <iostream>
#include "stdlib.h"
#include <cmath>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
using namespace std;
/****************************************************************************************************/
int N; // 블록의 갯수
constexpr int MOD = 10000000;
// [블록의 총 갯수] [첫 행의 갯수]
int cache[101][101];
// blocks : 사용 가능한 남은 블록의 갯수
int calc(int blocks)
{
// 기본 케이스 세팅
for (int i = 1; i <= N; ++i)
cache[i][i] = 1;
// 블록의 총 갯수
for (int n = 2; n <= blocks; ++n)
{
// 제일 윗 행의 갯수
for (int first = 1; first < n; ++first)
{
// 다음 하위 블록의 첫 행의 갯수
for (int second = 1; second <= n - first; ++second)
{
int add = cache[n - first][second] % MOD;
int multiply = first + second - 1;
cache[n][first] = (cache[n][first] + (add * multiply) % MOD) % MOD;
}
}
}
int sum = 0;
for (int i = 1; i <= blocks; ++i)
sum += cache[blocks][i];
return sum;
}
void sol()
{
//fill(&cache[0][0], &cache[100][0] + sizeof(cache) / sizeof(cache[0][0]), -1);
fill_n(&cache[0][0], 101 * 101, 0);
cout << calc(N) % MOD << endl;
}
void inputHandler()
{
cin >> N;
}
int main()
{
int cases;
cin >> cases;
while (cases--)
{
inputHandler();
sol();
}
return 0;
}
그런데 책에서는 좀 더 깔끔하게, 재귀로 풀고 있다. 참고로만 첨부하겠다 ㅋㅋ
#include <iostream>
#include "stdlib.h"
#include <cmath>
#include <vector>
#include <map>
#include <algorithm>
#include <unordered_map>
using namespace std;
/****************************************************************************************************/
int N; // 블록의 갯수
constexpr int MOD = 10000000;
// [블록의 총 갯수] [첫 행의 갯수]
int cache[101][101];
// n 개의 정사각형이면서, 맨 위의 가로줄에 first 개의
// 정사각형을 포함하는 폴리오미노의 수를 반환
int calc(int n, int first)
{
// 기저 사례 : n == first
if (n == first)
return 1;
// 메모이제이션
int& ret = cache[n][first];
if (ret != -1)
return ret;
ret = 0;
for (int second = 1; second <= n - first; ++second)
{
int add = second + first - 1;
add *= calc(n - first, second);
add %= MOD;
ret += add;
ret %= MOD;
}
return ret;
}
void sol()
{
fill_n(&cache[0][0], 101 * 101, -1);
int sum = 0;
for (int i = 1; i <= N; ++i)
sum = (sum + calc(N, i)) % MOD;
cout << sum << endl;
}
void inputHandler()
{
cin >> N;
}
int main()
{
int cases;
cin >> cases;
while (cases--)
{
inputHandler();
sol();
}
return 0;
}
'Data Structures, Algorithm > 종만북' 카테고리의 다른 글
[종만북 문제] 두니발 박사의 탈옥 (문제 ID : NUMB3RS, 난이도 : 중) (0) | 2024.03.13 |
---|---|
[종만북 문제] 비대칭 타일링 (문제 ID : ASYMTILING, 난이도 : 하) (0) | 2024.03.12 |
[종만북 문제] 달팽이 (문제 ID : SNAIL, 난이도 : 하) (0) | 2024.03.12 |
[종만북 문제] 삼각형 위의 최대 경로 수 세기 (문제 ID : TRIPATHCNT, 난이도 : 중) (0) | 2024.03.12 |
[종만북 문제] 타일링 (문제 ID : TILING2, 난이도 : 하) (0) | 2024.03.12 |
Comments