2019. 5. 23. 23:14ㆍ[개발] 지식/알고리즘 문제풀이
문제 정보
시간 : 1000ms
제한 메모리 : 65536kb
문제
정사각형들의 변들을 서로 완전하게 붙여 만든 도형들을 폴리오미노(Polyomino)라고 부릅니다. n개의 정사각형으로 구성된 폴리오미노들을 만들려고하는데, 이 중 세로로 단조(monotone)인 폴리오미노의 수가 몇 개나 되는지 세고 싶습니다. 세로로 단조라는 말은 어떤 가로줄도 폴리오미노를 두 번 이상 교차하지 않는다는 뜻입니다.
예를 들어 그림 (a)는 정상적인 세로 단조 폴리오미노입니다. 그러나 (b)는 점선이 폴리오미노를 두 번 교차하기 때문에 세로 단조 폴리오미노가 아닙니다. (c)는 맨 오른쪽 아래 있는 정사각형이 다른 정사각형과 변을 완전히 맞대고 있지 않기 때문에 폴리오미노가 아닙니다.
n개의 정사각형으로 구성된 세로 단조 폴리오미노의 개수를 세는 프로그램을 작성하세요.
입력
입력의 첫 줄에는 테스트 케이스의 수 C (1≤C≤50)가 주어집니다. 그 후 각 줄에 폴리오미노를 구성할 정사각형의 수 n (1≤n≤100)이 주어집니다.
출력
각 테스트 케이스마다, n개의 정사각형으로 구성된 세로 단조 폴리오미노의 수를 출력합니다. 폴리오미노의 수가 10,000,000 이상일 경우 10,000,000으로 나눈 나머지를 출력합니다.
예제 입력
3
2
4
92
예제 출력
2
19
4841817
소스
package apss;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Poly {
public static int N;
public static final int MOD = 10*1000*1000;
public static int[][] cache;
public static void main(String[] args) throws NumberFormatException, IOException {
// TODO Auto-generated method stub
System.setIn(new FileInputStream("D://sample_input.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
int T = Integer.parseInt(br.readLine().trim());
for(int testCase=1; testCase <= T; testCase++) {
N = Integer.parseInt(br.readLine().trim());
cache = new int[101][101];
for(int i=0; i<101; i++) {
for(int j=0; j<101; j++) {
cache[i][j] = -1;
}
}
int result = 0;
for(int i=1; i<=N; i++) {
result += poly(N,i);
result %= MOD;
}
bw.flush();
bw.write(result + "\n");
}
bw.close();
}
public static int poly(int n, int first) {
// 기저 사례: n == first
if(n==first) {
return 1;
}
// 메모이제이션
if(cache[n][first] != -1) {
return cache[n][first];
}
int ret = 0;
for(int second=1; second <= n-first; ++second) {
int add = second + first - 1;
add *= poly(n-first, second);
add %= MOD;
ret += add;
ret %= MOD;
}
cache[n][first] = ret;
return ret;
}
}
풀이
제일 위 가로줄에 포함할 정사각형의 수 first,
따라서 poly(n, first)는 n개의 정사각형으로 첫줄에 first개의 정사각형으로 이루어진 폴리오미노 수.
모든 정사각형은 붙어 있어야 하므로(세로 단조 폴리오미노) 첫줄에 가능한 경우의 수는 n.
결국 poly(n, first) = first * (poly(n-first, 1) + poly(n-first, 2) + … + poly(n-first, n-first).
하지만 두번째 줄의 정사각형 개수에 따라 붙일 수 있는 방법의 수가 정해진다.
First + second -1 이 첫째줄과 둘째줄을 붙일 수 있는 경우의 수이다.
따라서 이렇게 정의할 수 있다.
Poly(n, first) = (second + first - 1) * (poly(n-first, 1) + poly(n-first, 2) + … + poly(n-first, n-fisrst))
'[개발] 지식 > 알고리즘 문제풀이' 카테고리의 다른 글
[알고스팟] 도시락 데우기 (LUNCHBOX) (0) | 2019.07.20 |
---|---|
[알고스팟] 두니발 박사의 탈옥 (NUMB3RS) (0) | 2019.06.07 |
[알고스팟] ASYMTILING (비대칭 타일링) (0) | 2019.05.06 |
[알고스팟] Quantization (0) | 2019.05.05 |
[문제][알고스팟]WILDCARD (0) | 2019.02.06 |