백준의 2048(Easy)(12100) 문제이다.

[ 문제 바로가기 ]


[ 문제풀이 ]

1) 조금 까다로운 시뮬레이션 문제이다. 천천히 단계별로 알아가보도록 하자.

    먼저 우리는 방향을 선택해줘야 한다. 최대 5번을 이동해서 만들 수 있을 때, 어느 방향으로 보드에 있는 숫자들을

    움직일 것인지를 결정해주어야 한다.

    만약 5번중에 첫번째로 동쪽으로 움직여 줬다고 생각해보자. 그럼 두번째는 어느방향으로 움직여줄 수 있을까?

    동서남북 4방향 중에 어떤방향이든 가능하다. 세번째 네번째 다섯번째도 모두 마찬가지이다.

    즉, { 1번째 움직임, 2번째 움직임, 3번째 움직임, 4번째 움직임, 5번째 움직임 } 을 나타내면

    { 동동동동동 } , { 동동동동서 } , { 동동동동남 } , { 동동동동북 } .... { 북북북북남 } , { 북북북북북 } 과 같은 경우가 쭉

    나열될 것이다.

    이거를 어떻게 구할 수 있을까?? 바로 중복순열이다. 일단 뭐 같은 방향이 여러분 나올 수 있다는 것에서 중복이라는 것을

    알겠는데 왜 순열인지 알아보자.

    보드를 동쪽으로 움직이고 서쪽으로 움직이는 것과 서쪽으로 움직이고 동쪽으로 움직이는 것의 결과가 같을까 ??

    아니다 다를 것이다.

    이러한 맵이 있다고 생각해보자. (그냥 간략하게 가져온 것입니다. NxN 으로 주어진다는 것 알고

     알고있습니다.)

     이 때, 동쪽으로 움직이고 서쪽으로 움직인 후의 보드의 상황과 서쪽으로 움직이고 동쪽으로 움직였을 때의 보드의 상태

     는 어떨까 ??

    

    아마 위의 그림과 같을 것이다. 위의 그림에서 위에 있는 그림은 동쪽으로 움직이고 서쪽으로 움직인 경우, 밑에 그림이

    서쪽으로 움직이고 동쪽으로 움직이는 경우이다.

    보면 보드의 상태가 서로 다르다는 것을 알 수 있다. 즉, 우리는 순서에 영향을 미치는 중복적으로 선택이 가능한 중복순열을

    구현해 주면 된다. 중복 순열을 아직 잘 모른다면 아래의 글을 읽고 오도록 하자.

    [ 중복순열 알아보기(Click) ]


2) 중복순열을 통해서 이제 방향을 모두 정해주었다면 보드를 실제로 움직이면서 합칠 걸 합쳐주기만 하면 된다.

   합쳐주는 부분은 사실은 특별한 알고리즘이 사용되지는 않아서 그냥 본인이 합친 방법만 설명하고 끝내겠다.

   먼저 방법은 총 3단계로 나뉜다. (보드를 오른쪽으로 움직인다고 가정하고 진행하겠습니다.)

   1. 같은 숫자끼리 합쳐주고 뭐고 그런거 없이 무조건 보드를 싹다 오른쪽으로 옮겨준다.

     이런식으로 바뀌게 !

   2. 이제 가장 오른쪽부터 현재 자기 좌표 - 1 한 값과 값이 같은지 체크한 후에 같다면 더해주고 칸을 없애는 일을 해준다.

    이런식으로 !

     보면 그림이 조금 이상하다. 왜 저렇게 했을까?? 바로 한번 합쳐진 블럭은 또 합쳐질 수 없다는 조건 때문이다.

     가장 윗줄인 (0 , 2 , 4, 4)로 이해해보자. 가장 오른쪽부터 현재 자기좌표 -1 한 값과 비교한다고 했다.

     즉, (0, 3)의 4와 (0, 2)의 4를 비교해서 같은 값이므로 (0, 3)을 8로 만들어주고 (0, 2)를 0으로 만들어 줌으로써 빈칸으로

     만들어 주었다. 그 다음 (0, 2)과 (0, 1)을 비교해보자. (0, 2)는 위의 과정에서 0이 되었으므로 (0, 1)과 다르기 때문에 넘어간다.

     이런식으로 계산을 해주면 한번 합쳐진 블럭은 절대로 또 다시 합쳐지지 않는다.

     하지만 여기서 끝내버리면 안된다. 1 번에서 했던 과정을 한번 더 반복함으로써 맵의 전체 숫자들을 다시 오른쪽으로 옮겨

     줘야 한다.

    이렇게 되도록 !


이 후, 맵 전체를 탐색하면서 최댓값을 찾아주고 또 다른 중복순열을 통해 나온 수열들로 계산을 반복해주면 된다.

물론, 맵을 계속 움직여주고 합쳐주고 없애주고 해야 하기 때문에 맵 복사를 반드시 해줘야 한다.


[ 소스코드 ]

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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
#include<iostream>
#include<cstring>
 
#define endl "\n"
#define MAX 20
using namespace std;
 
int N, Answer;
int MAP[MAX][MAX];
int C_MAP[MAX][MAX];
int Select[5];
bool Visit[MAX][MAX];
 
int Bigger(int A, int B) { if (A > B) return A; return B; }
 
void Input()
{
    cin >> N;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            cin >> MAP[i][j];
        }
    }
}
 
void Copy_MAP()
{
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            C_MAP[i][j] = MAP[i][j];
        }
    }
}
 
void Move_Left()
{
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N - 1; j++)
        {
            bool Check = false;
            if (C_MAP[i][j] == 0)
            {
                int k = j + 1;
                while (k <= N - 1)
                {
                    if (C_MAP[i][k] != 0)
                    {
                        Check = true;
                        break;
                    }
                    k++;
                }
                if (Check == true)
                {
                    C_MAP[i][j] = C_MAP[i][k];
                    C_MAP[i][k] = 0;
                }
            }
        }
    }
 
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N - 1; j++)
        {
            if (C_MAP[i][j] == C_MAP[i][j + 1])
            {
                C_MAP[i][j] = C_MAP[i][j] * 2;
                C_MAP[i][j + 1= 0;
            }
        }
    }
 
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N - 1; j++)
        {
            bool Check = false;
            if (C_MAP[i][j] == 0)
            {
                int k = j + 1;
                while (k <= N - 1)
                {
                    if (C_MAP[i][k] != 0)
                    {
                        Check = true;
                        break;
                    }
                    k++;
                }
                if (Check == true)
                {
                    C_MAP[i][j] = C_MAP[i][k];
                    C_MAP[i][k] = 0;
                }
            }
        }
    }
}
 
void Move_Right()
{
    for (int i = 0; i < N; i++)
    {
        for (int j = N - 1; j > 0; j--)
        {
            bool Check = false;
            if (C_MAP[i][j] == 0)
            {
                int k = j - 1;
                while (k >= 0)
                {
                    if (C_MAP[i][k] != 0)
                    {
                        Check = true;
                        break;
                    }
                    k--;
                }
                if (Check == true)
                {
                    C_MAP[i][j] = C_MAP[i][k];
                    C_MAP[i][k] = 0;
                }
            }
        }
    }
 
    for (int i = 0; i < N; i++)
    {
        for (int j = N - 1; j > 0; j--)
        {
            if (C_MAP[i][j] == C_MAP[i][j - 1])
            {
                C_MAP[i][j] = C_MAP[i][j] * 2;
                C_MAP[i][j - 1= 0;
            }
        }
    }
 
    for (int i = 0; i < N; i++)
    {
        for (int j = N - 1; j > 0; j--)
        {
            bool Check = false;
            if (C_MAP[i][j] == 0)
            {
                int k = j - 1;
                while (k >= 0)
                {
                    if (C_MAP[i][k] != 0)
                    {
                        Check = true;
                        break;
                    }
                    k--;
                }
                if (Check == true)
                {
                    C_MAP[i][j] = C_MAP[i][k];
                    C_MAP[i][k] = 0;
                }
            }
        }
    }
}
 
void Move_Up()
{
    for (int i = 0; i < N - 1; i++)
    {
        for (int j = 0; j < N; j++)
        {
            bool Check = false;
            if (C_MAP[i][j] == 0)
            {
                int k = i + 1;
                while (k <= N - 1)
                {
                    if (C_MAP[k][j] != 0)
                    {
                        Check = true;
                        break;
                    }
                    k++;
                }
 
                if (Check == true)
                {
                    C_MAP[i][j] = C_MAP[k][j];
                    C_MAP[k][j] = 0;
                }
            }
        }
    }
 
    for (int i = 0; i < N - 1; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (C_MAP[i][j] == C_MAP[i + 1][j])
            {
                C_MAP[i][j] = C_MAP[i][j] * 2;
                C_MAP[i + 1][j] = 0;
            }
        }
    }
 
    for (int i = 0; i < N - 1; i++)
    {
        for (int j = 0; j < N; j++)
        {
            bool Check = false;
            if (C_MAP[i][j] == 0)
            {
                int k = i + 1;
                while (k <= N - 1)
                {
                    if (C_MAP[k][j] != 0)
                    {
                        Check = true;
                        break;
                    }
                    k++;
                }
 
                if (Check == true)
                {
                    C_MAP[i][j] = C_MAP[k][j];
                    C_MAP[k][j] = 0;
                }
            }
        }
    }
}
 
void Move_Down()
{
    for (int i = N - 1; i > 0; i--)
    {
        for (int j = 0; j < N; j++)
        {
            bool Check = false;
            if (C_MAP[i][j] == 0)
            {
                int k = i - 1;
                while (k >= 0)
                {
                    if (C_MAP[k][j] != 0)
                    {
                        Check = true;
                        break;
                    }
                    k--;
                }
                if (Check == true)
                {
                    C_MAP[i][j] = C_MAP[k][j];
                    C_MAP[k][j] = 0;
                }
            }
        }
    }
 
    for (int i = N - 1; i > 0; i--)
    {
        for (int j = 0; j < N; j++)
        {
            if (C_MAP[i - 1][j] == C_MAP[i][j])
            {
                C_MAP[i][j] = C_MAP[i][j] * 2;
                C_MAP[i - 1][j] = 0;
            }
        }
    }
    for (int i = N - 1; i > 0; i--)
    {
        for (int j = 0; j < N; j++)
        {
            bool Check = false;
            if (C_MAP[i][j] == 0)
            {
                int k = i - 1;
                while (k >= 0)
                {
                    if (C_MAP[k][j] != 0)
                    {
                        Check = true;
                        break;
                    }
                    k--;
                }
                if (Check == true)
                {
                    C_MAP[i][j] = C_MAP[k][j];
                    C_MAP[k][j] = 0;
                }
            }
        }
    }
 
}
 
int Find_Max()
{
    int Max = 0;
    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < N; j++)
        {
            if (C_MAP[i][j] > Max)
            {
                Max = C_MAP[i][j];
            }
        }
    }
    return Max;
}
 
void Play_The_Game()
{
    for (int i = 0; i < 5; i++)
    {
        int Dir = Select[i];
        if (Dir == 0) Move_Right();
        else if (Dir == 1) Move_Left();
        else if (Dir == 2) Move_Down();
        else if (Dir == 3) Move_Up();
    }
 
    Answer = Bigger(Answer, Find_Max());
}
 
void Select_Direction(int Idx, int Cnt)
{
    if (Cnt == 5)
    {
        Copy_MAP();
        Play_The_Game();
        return;
    }
 
    for (int i = 0; i < 4; i++)
    {
        Select[Cnt] = i;
        Select_Direction(i, Cnt + 1);
    }
}
 
void Solution()
{
    Select_Direction(00);
    cout << Answer << endl;
}
 
void Solve()
{
    Input();
    Solution();
}
 
int main(void)
{
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
 
    //freopen("Input.txt", "r", stdin);
    Solve();
 
    return 0;
}
cs

   

+ Recent posts