[C++] 백준(BOJ) - 12100 : 2048 (easy)

인프런에 있는 큰돌님의 강의 10주완성 C++ 코딩테스트 | 알고리즘 코딩테스트를 듣고 정리한 필기입니다.

문제

BOJ - 12100 : 2048 (easy)(링크)

이 게임에서 한 번의 이동은 보드 위에 있는 전체 블록을 상하좌우 네 방향 중 하나로 이동시키는 것이다. 이때, 같은 값을 갖는 두 블록이 충돌하면 두 블록은 하나로 합쳐지게 된다. 한 번의 이동에서 이미 합쳐진 블록은 또 다른 블록과 다시 합쳐질 수 없다. (실제 게임에서는 이동을 한 번 할 때마다 블록이 추가되지만, 이 문제에서 블록이 추가되는 경우는 없다)

2048 게임은 보드의 크기가 N×N 이다. 보드의 크기와 보드판의 블록 상태가 주어졌을 때, 최대 5번 이동해서 만들 수 있는 가장 큰 블록의 값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.

출력

최대 5번 이동시켜서 얻을 수 있는 가장 큰 블록을 출력한다.

알고리즘

  1. 구현
  2. 완전탐색

풀이

  • 90도 회전 알고리즘
    • i, j => n-j-i, i
  • Temp 배열 사용
    • 같으면 추가
    • 다르면 넘어가기

코드

// BOJ-12100 : 2048 (easy)
#include <bits/stdc++.h>
using namespace std;

int n, res;

struct Board {
	int a[24][24];

	// 1. 배열이 90도 회전하는 로직
	void Rotate90()
	{
		int tmp[24][24];
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++) {
				tmp[i][j] = a[n - j - 1][i];
			}
		}
		memcpy(a, tmp, sizeof(a));
	}

	// 2. 메인로직
	
	/// <summary>
	/// [2][0][2][0] => [4][0][0][0]
	/// </summary>
	void MoveLogic()
	{
		int tmp[24][24];
		for (int i = 0; i < n; i++)
		{
			int c = -1, d = 0;
			for (int j = 0; j < n; j++)
			{
				if (a[i][j] == 0) continue; // 0이면 넘어가고
				if (d && a[i][j] == tmp[i][c]) tmp[i][c] *= 2, d = 0;
				else {
					tmp[i][++c] = a[i][j];
					d = 1;
				}
			}
			for (c++; c < n; c++) tmp[i][c] = 0;
		}
		memcpy(a, tmp, sizeof(a));
	}

	void GetMax()
	{
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				res = max(res, a[i][j]);
			}
		}
	}
};

// 완전탐색
void go(Board b, int here)
{
	// 기저사례
	if (here == 5)
	{
		b.GetMax();
		return;
	}

	for (int i = 0; i < 4; i++)
	{
		Board d = b;
		d.MoveLogic();
		go(d, here + 1);
		b.Rotate90(); // 네방향 탐색 구현
	}
	return;
}

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	cin >> n;
	Board bd;

	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++)
		{
			cin >> bd.a[i][j];
		}
	}

	go(bd, 0);
	cout << res << '\n';

	return 0;
}

평가

  • 배열의 90도 회전 알고리즘 필수적으로 기억
    • i, j <= n-j-1, i
  • 구조체를 활용한 메소드 구현
  • 완전탐색을 위한 기저조건, for문을 활용해서 90도 회전 알고리즘 재귀함수 아래에 넣어서 구현

© 2023 Jinsoo Lee. All rights reserved.

Powered by Hydejack v9.1.6