본문 바로가기
알고리즘/삼성 SW 역량 테스트 기출 문제

[C++][BOJ] 삼성 SW 역량 테스트 기출 문제 - 12100번 2048 (Easy)

by 개발자J의일상 2021. 5. 11.
반응형

www.acmicpc.net/problem/12100

 

12100번: 2048 (Easy)

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

www.acmicpc.net

 

굉장히 복잡한 문제처럼 보이지만 N이 20이 max이고 5번 이동만 하면 되기 때문에 완전탐색 기법을 사용하여 다 해보면 된다.

map을 매번 저장해주고 [왼쪽,오른쪽,위,아래] 로 블록을 밀어주고 그 블록을 그대로 또 한번 [왼쪽,오른쪽,위,아래] 방향으로 밀어주면서 이렇게 5번을 해주고 5번이 됐을 때 블록의 최대 값을 return해주면 모든 case를 다 돌려 볼 수 있다.

 

  1           2          3           4          5

왼쪽 -> 왼쪽 -> 왼쪽 -> 왼쪽 -> 왼쪽 => max값

왼쪽 -> 왼쪽 -> 왼쪽 -> 왼쪽 -> 오른쪽 => max값

왼쪽 -> 왼쪽 -> 왼쪽 -> 왼쪽 -> 위 => max값

왼쪽 -> 왼쪽 -> 왼쪽 -> 왼쪽 -> 아래 => max값

  

이런식으로 쭈욱 완전 탐색을 하는 것이다. 저렇게 위의 숫자를 count로 하여 계속해서 max값을 return해주면 정답이 나온다.

 

재귀에 대해 이해를 반드시 해야 풀 수 있는 문제이다.

 

또한 queue를 통해 2 2 2 가 있으면 2 2 2 를 넣고 앞에서 부터 2, 2 / 2 를 찾아 4 2 를 만들어 준다. 

위로 민다고 치면 2 4 8인데 여기서 합칠 수 있는게 없으므로 2 4 8을 그대로 block에 저장해야 한다.

 

이제 코드를 보자.

 

#include <iostream>
#include <queue>
using namespace std;
#define MAX_MAP 21

int map[MAX_MAP][MAX_MAP];
int N;

void shift(int block[MAX_MAP][MAX_MAP], int pos)
{
	queue<int> q;
	switch (pos)
	{
	//왼쪽
	case 0:
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
            	//0이 아닌 경우에만 밀면 됨으로 0이 아닌 경우만 queue에 저장
				if (block[i][j])
					q.push(block[i][j]);
                //queue에 넣었으니 0으로 초기화
				block[i][j] = 0;
			}
			int pos = 0;
			//q가 비어질 때 까지 
			while (!q.empty())
			{
				int data = q.front();
				q.pop();
				//현재 block의 위치가 0이면 값을 넣어줌 (처음 case)
				if (block[i][pos] == 0)
				{
					block[i][pos] = data;
				}
                //현재 block의 위치와 data가 같으면 동일한 숫자가 있는 것으로 *2 해줌 (2 / 2 case)
				else if (block[i][pos] == data)
				{
					block[i][pos] = block[i][pos] * 2;
					pos++;
				}
                //다른 값이 있으면 block의 다음 위치에 (2 / 4 case)
				else
				{
					pos++;
					block[i][pos] = data;
				}
			}
		}
		break;
    //오른쪽
	case 1:
		for (int i = 0; i < N; i++)
		{
        	//뒤부터 -> 오른쪽으로 미는 것이기 때문에
			for (int j = N - 1; j >= 0; j--)
			{
				if (block[i][j])
					q.push(block[i][j]);
				block[i][j] = 0;
			}
            //뒤부터 집어 넣기
			int pos = N - 1;

			while (!q.empty())
			{
				int data = q.front();
				q.pop();
				if (block[i][pos] == 0)
				{
					block[i][pos] = data;
				}
				else if (block[i][pos] == data)
				{
					block[i][pos] = block[i][pos] * 2;
					pos--;
				}
				else
				{
					pos--;
					block[i][pos] = data;
				}
			}
		}
		break;
	//위
	case 2:
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
            	//i, j 반대로
				if (block[j][i])
					q.push(block[j][i]);
				block[j][i] = 0;
			}
			int pos = 0;

			while (!q.empty())
			{
				int data = q.front();
				q.pop();
				if (block[pos][i] == 0)
				{
					block[pos][i] = data;
				}
				else if (block[pos][i] == data)
				{
					block[pos][i] = block[pos][i] * 2;
					pos++;
				}
				else
				{
					pos++;
					block[pos][i] = data;
				}
			}
		}
		break;
	//아래 
	case 3:
		for (int i = 0; i < N; i++)
		{
			for (int j = N - 1; j >= 0; j--)
			{
            	//i, j 반대로
				if (block[j][i])
					q.push(block[j][i]);
				block[j][i] = 0;
			}
			int pos = N - 1;

			while (!q.empty())
			{
				int data = q.front();
				q.pop();
				if (block[pos][i] == 0)
				{
					block[pos][i] = data;
				}
				else if (block[pos][i] == data)
				{
					block[pos][i] = block[pos][i] * 2;
					pos--;
				}
				else
				{
					pos--;
					block[pos][i] = data;
				}
			}
		}
		break;
	}
}
int solve(int block[MAX_MAP][MAX_MAP], int count)
{
	int maxVal = -1;

	if (count == 5)
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				if (block[i][j] > maxVal) maxVal = block[i][j];
			}
		}
		return maxVal;
	}

	//현재 Block을 저장해 놓을 Block선언
	int copyBlock[MAX_MAP][MAX_MAP] = { 0, };

	//네 방향
	for (int i = 0; i < 4; i++)
	{
		//Block copy
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				copyBlock[i][j] = block[i][j];
			}
		}
        //Block이동
		shift(copyBlock, i);
        //다음 count로 넘어감
		maxVal = max(maxVal,solve(copyBlock, count + 1));
	}
	return maxVal;
}
int main()
{
	cin >> N;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			cin >> map[i][j];
		}
	}
	cout << solve(map, 0) << endl;
}

 

300x250

댓글