매일 C++ day 15 / 2048 (Easy)

2021-06-12

2048 (Easy)

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

동서남북 모든 방향으로 움직이는 함수를 각각 만들다 보니 코드가 너무 길어져 만든 나도 알아볼 수 없었다.

그래서 숏코딩 코드를 보고 주석을 달아봤다.


입력

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


출력

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


int main() {
	cin >> n;
	int arr[20][20];
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> arr[i][j];
		}
	}
	dfs(0, arr);
	cout << maxv;
}

dfs

깊이 우선 탐색의 매개변수로 depth와 보드판 arr을 받는다.

기존에 내가 만든 코드는 4방향 각각 함수를 만든 반면

여기서는 한 방향으로만 움직이는 대신 보드판을 회전시킨다.

int temp[20][20];
for (int i = 0; i < n; i++) 
{
  for (int j = 0; j < n; j++) 
  {
    temp[i][j] = arr[n - j - 1][i];
  }
}
memcpy(arr, temp, sizeof(temp));

왼쪽 이동

새로운 보드판 brr을 0으로 초기화한다.

cur은 다음 brr 블록을 가르키고 ok는 블록을 하나로 합칠 수 있는지의 여부를 알려준다.

cur과 ok가 있으면 코드를 매우 많이 단축시킬 수 있다!

ok가 1이고 brr[i][cur - 1] == arr[i][j] 이면, brr[i][cur - 1]의 값을 두배로 증가시키고 ok를 0으로 바꾸지만 cur은 증가하지 않는다.

ok가 0이라면 brr[i][cur]에 arr[i][j]을 넣고 cur을 1 증가시킨다.

for (int i = 0; i < n; i++) {
  int cur = 0, ok = 0;
  for (int j = 0; j < n; j++) {
    if (arr[i][j]) {
      if (ok && brr[i][cur - 1] == arr[i][j]) {
        brr[i][cur - 1] <<= 1;
        ok = 0;
      }
      else {
        brr[i][cur++] = arr[i][j];
        ok = 1;
      }
    }
  }
}
void dfs(int depth, int arr[20][20]) 
{	
	if (depth >= 5) 
  {
		for (int i = 0; i < n; i++) 
    {
			for (int j = 0; j < n; j++) 
      {
				if (arr[i][j] && arr[i][j] > maxv) 
        {
					maxv = arr[i][j];
				}
			}
		}
		return;
	}
  
  // 깊이 5까지 탐색하고 최대값을 반환한다.
  

	for (int i = 0; i < 4; i++) 
  {
		int brr[20][20];
		memset(brr, 0, sizeof(brr));
    // 보드를 0으로 초기화

		for (int i = 0; i < n; i++) 
    {
			int cur = 0, ok = 0;
			for (int j = 0; j < n; j++) 
      {
				if (arr[i][j]) 
        { 
					if (ok && brr[i][cur - 1] == arr[i][j]) 
          {
						brr[i][cur - 1] <<= 1; 
						ok = 0;
					}
					else 
          {
						brr[i][cur++] = arr[i][j];
						ok = 1;
					}
				}
			}
		}

		dfs(depth + 1, brr);
  
  
    // !!!!보드판을 오른쪽 90도 회전!!!!
		int temp[20][20];
		for (int i = 0; i < n; i++) 
    {
			for (int j = 0; j < n; j++) 
      {
				temp[i][j] = arr[n - j - 1][i];
			}
		}
		memcpy(arr, temp, sizeof(temp));
	}
}