2018년 7월 30일 월요일

백준 2448: 별 찍기 - 11 (프랙탈 구조) 풀이

문제 링크

https://www.acmicpc.net/problem/2448



더 좋은 풀이 방법이 많이 있을텐데, 클래스를 사용해보려고 했다.

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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include <iostream>
#include <math.h> // for pow,sqrt func. ex) pow(2, 3) = 2^3 = 8
#include <memory.h> // for memset func.
/*
    입력: 첫째 줄에 N이 주어진다. N은 항상 3*2^k 수이다. (3, 6, 12, 24, 48, ...) k <= 10
    출력: 첫째 줄부터 N번째 줄까지 별을 출력한다. 아래 규칙으로..
                                   *                        
                                  * *                       
                                 *****                      
                                *     *                     
                               * *   * *                    
                              ***** *****                   
                             *           *                  
                            * *         * *                 
                           *****       *****                
                          *     *     *     *               
                         * *   * *   * *   * *              
                        ***** ***** ***** *****             
                       *                       *            
                      * *                     * *           
                     *****                   *****          
                    *     *                 *     *         
                   * *   * *               * *   * *        
                  ***** *****             ***** *****       
                 *           *           *           *      
                * *         * *         * *         * *     
               *****       *****       *****       *****    
              *     *     *     *     *     *     *     *   
             * *   * *   * *   * *   * *   * *   * *   * *  
            ***** ***** ***** ***** ***** ***** ***** *****
            
    알고리즘을 맨날 C스타일로만 풀고 있는 것 같아서 클래스를 써보자..
    
    프랙탈 구조의 문제다. 이전 단계의 트리를 다음 단계에 좌, 우로 복사하는 방식으로 구현했다.
    좌표마다 별을 찍는 것보다 어차피 프랙탈 구조니 메모리를 한 번에 복사해버리는 방식이 더 빠를 것으로 판단했다.
    클래스를 억지로 쓰려고 했더니 뭔가 더 지저분해진 것 같지만...
*/
class DrawBoard
{
public:
    DrawBoard(int xSize, int ySize) : xSize_(xSize), ySize_(ySize)
    {
        pBoard_ = new char*[ySize_];
        
        for(int loopCount = 0; loopCount < ySize_; loopCount++)
        {
            pBoard_[loopCount] = new char[xSize_];
            memset(pBoard_[loopCount], ' 'sizeof(char)*xSize_);
        }
    }
    ~DrawBoard()
    {
        for(int loopCount = 0; loopCount < ySize_; loopCount++)
        {
            delete[] pBoard_[loopCount];
        }
    }
    
    void PrintBoard()
    {
        for(int yLoop = 0; yLoop < ySize_; yLoop++)
        {
            for(int xLoop = 0; xLoop < xSize_; xLoop++)
            {
                std::cout << pBoard_[yLoop][xLoop];
            }
            std::cout << "\n";
        }
    }
    
    bool CheckCoord(int x, int y)
    {
        if(x < 0 || x >= xSize_ || y < 0 || y >= ySize_)
        {
            return false;
        }    
        
        return true;
    }
    
    void DrawStar(int x, int y)
    {    
        if(false == CheckCoord(x, y))
            return;
        
        pBoard_[y][x] = '*';
    }
    
    void DrawFirstTree(int x, int y)
    {
            DrawStar(x, y);
            
            DrawStar(x-1, y+1);
            DrawStar(x+1, y+1);
            
            DrawStar(x-2, y+2);
            DrawStar(x-1, y+2);
            DrawStar(x, y+2);
            DrawStar(x+1, y+2);
            DrawStar(x+2, y+2);
    }
    
    void CopyAndDrawTree(int x, int y, int loopCount)
    {    
        
        if(log2(ySize_/3< loopCount)
            return;
        
        // 이전 단계 트리의 시작x좌표와 가로 길이, 세로 길이를 구한다.
        int _copyWidth  = 2 * (3 * pow(2, loopCount-1)) -1;
        int _copyHeight = 3 * pow(2, loopCount-1);
    
        for(int heightLoop = 0; heightLoop <= _copyHeight; heightLoop++)
        {            
            if(CheckCoord(x - _copyWidth, y + _copyHeight + heightLoop) &&
               CheckCoord(x + 1, y + _copyHeight + heightLoop))
            {
                // 좌 트리 복사
                memcpy(&pBoard_[y + _copyHeight + heightLoop][x - _copyWidth], &pBoard_[heightLoop][x - (_copyWidth/2)], _copyWidth);
                // 우 트리 복사
                memcpy(&pBoard_[y + _copyHeight + heightLoop][x + 1], &pBoard_[heightLoop][x - (_copyWidth/2)], _copyWidth);
            }
        }
        
        CopyAndDrawTree(x, y, ++loopCount);
    }
    
    void DrawTree(int x, int y, int loopCount)
    {
        if(0 == loopCount)
            DrawFirstTree(x, y);
        if(0 == log2(ySize_/3))
            return;
        
        CopyAndDrawTree(x, y, ++loopCount);
    }
    
private:
    char **pBoard_;
    int  xSize_;
    int  ySize_;
};
void Solution(int &lineNum)
{    
    DrawBoard _drawBoard(2*lineNum - 1, lineNum);
    
    _drawBoard.DrawTree((2*lineNum - 1)/200);
    _drawBoard.PrintBoard();
}
int main() 
{    
    int input = 0;
    std::cin >> input;
    
    Solution(input);
    
    return 0;
}
cs

댓글 없음:

댓글 쓰기

A*, JPS 길찾기 알고리즘 시뮬레이션 사이트

https://qiao.github.io/PathFinding.js/visual/ 길 찾기 알고리즘 시행 과정을 보여주는 사이트다. 링크 메모..