알고리즘/algospot

algospot POLY

꾸준함. 2018. 1. 28. 20:35

문제링크입니다: https://algospot.com/judge/problem/read/POLY

솔직히 손도 대지 못한 문제였습니다.

'폴리오미노'라는 개념을 처음 알았고 '세로로 단조'라는 표현도 처음 알았기 때문입니다.

책의 풀이는 정말 끝내줍니다. 최근 푼 문제들처럼 동적 계획법을 사용하여 푸는데 첫번째 줄에 몇개의 블록을 사용할 것인지를 토대로 답을 구해내는 풀이였습니다.

풀이를 보면서 '아직 갈 길이 멀구나'라는 생각이 들면서도 흥미로워하는 것을 보면 프로그래밍이 적성에 맞는 편인 것 같습니다!


/*

정사각형들의 변들을 서로 완전하게 붙여 만든 도형들을 폴리오미노라고 한다

n개의 정사각형으로 구성된 폴리오미노들을 만들려고 하는데,

이 중 세로로 단조인 폴리오미노의 수가 몇개나 되는가?

 

세로로 단조라는 말은 어떤 가로줄도 폴리오미노를 두번 이상 교차하지 않는다는 뜻이다.

ex)

2개의 정사각형일 경우(2가지)

ㅁ ㅇㅇ

4개의 정사각형일 경우(19가지)

ㅁ ㅇㅇ ㅁㅁ ㅇ     ㅁ ㅇ    

   ㅇ ㅁ   ㅇㅇ ㅁㅁ ㅇㅇ ㅁㅁ

   ㅇ ㅁ        ㅁ ㅇ  

                             

ㅁㅁㅁ ㅇㅇㅇ ㅁㅁㅁ        

                ㅇㅇ ㅁㅁ

 

ㅇㅇ   ㅁㅁ   ㅇㅇ ㅁ      

  ㅇㅇ ㅁㅁ ㅇㅇ   ㅁㅁㅁ ㅇㅇㅇ

   

        ㅇ ㅁㅁㅁㅁ

ㅇㅇㅇ

*/

#include <iostream>

#include <cstring> //memset

using namespace std;

 

const int MOD = 10000000; //1,000,000을 넘어갈 경우 적절한 크기의 답을 구하기 위한 modulation

int cache[101][101]; //최대 100이고 0번째 index를 사용하지 않으므로

 

//n개의 정사각형으로 이루어졌고, 맨 위 가로줄에 first개의

//정사각형을 포함하는 폴리오미노의 수를 반환

int poly(int n, int first)

{

        //기저 사례:n==first

        if (n == first)

               return 1;

        //메모이제이션

        int &result = cache[n][first];

        if(result!=-1)

               return result;

        result = 0;

        //맨 위 가로줄에서부터 second번째 밑에 있는 층의 블록 수

        //poly(n, first)=(second+first-1) * poly(n-first, second);

        for (int second = 1; second <= n - first; second++)

        {

               //맨 윗줄에 first개의 정사각형이 있고, 나머지 사각형으로 만든 폴리오미노의 첫 줄에 second개의

               //정사각형이 있다고 했을 때  이들을 붙일 수 있는 방법의 수는 first+second-1

               //ex) first 2 second 2(2+2-1=3가지)

               //  ㅁㅁ ㅁㅁ ㅁㅁ

               //ㅁㅁ   ㅁㅁ   ㅁㅁ

               //ex) first 2 second 3(2+3-1=4가지)

               //  ㅁㅁ     ㅁㅁ ㅁㅁ   ㅁㅁ

               //ㅁㅁㅁ ㅁㅁㅁ   ㅁㅁㅁ   ㅁㅁㅁ

               int add = second + first - 1;

               add *= poly(n - first, second); //n-first개의 정사각형 중 해당 층에는 second개 사용

               add %= MOD;

               result += add;

               result %= MOD;

        }

        return result;

}

 

int main(void)

{

        int test_case;

        cin >> test_case;

        if (test_case < 1 || test_case>50)

               exit(-1);

       

        for (int i = 0; i < test_case; i++)

        {

               int block, sum = 0;

               cin >> block;

               if (block < 1 || block>100)

                       exit(-1);

               memset(cache, -1, sizeof(cache));

               for (int j = 1; j <= block; j++)

               {

                       sum += poly(block, j);

                       sum %= MOD;

               }

               cout << sum << endl << endl;

        }

        return 0;

}



개발환경:Visual Studio 2017


지적, 조언, 질문 환영입니다! 댓글 남겨주세요~


[참고] 프로그래밍 대회에서 배우는 알고리즘 문제해결전략


반응형

'알고리즘 > algospot' 카테고리의 다른 글

최대 부분 수열 직접 구하기(LIS)  (3) 2018.01.31
algospot NUMB3RS  (0) 2018.01.29
algospot ASYMTILING  (0) 2018.01.28
algospot SNAIL  (0) 2018.01.28
algospot TRIPATHCNT  (0) 2018.01.27