12100 swift / c++ - 2048 (Easy)

2024. 9. 23. 01:16🐣/BOJ

문제 개요는 2048게임을 구현하는 것.

입력

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

출력

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

 

접근 방법. 4방향으로 합치고, 미는 dfs의 방법을 통해. 5번 할 수 있는 모든 방법을 찾아낸 뒤. 최대값으로 출력.

 

더보기
/* ************************************************************************** */
/*                                                                            */
/*                                                      :::    :::    :::     */
/*   Problem Number: 12100                             :+:    :+:      :+:    */
/*                                                    +:+    +:+        +:+   */
/*   By: chanhihi <boj.kr/u/chanhihi>                +#+    +#+          +#+  */
/*                                                  +#+      +#+        +#+   */
/*   https://boj.kr/12100                          #+#        #+#      #+#    */
/*   Solved: 2024/09/22 22:22:12 by chanhihi      ###          ###   ##.kr    */
/*                                                                            */
/* ************************************************************************** */

#include <iostream>
#include <vector>

using namespace std;

int n;
int maxNumber = 0;

int dx[] = {-1, 1, 0, 0};
int dy[] = {0, 0, -1, 1};

void move(int x, int y, int dir, vector<vector<int> > &board) {
  while (y + dy[dir] < n && x + dx[dir] < n && x + dx[dir] >= 0 &&
         y + dy[dir] >= 0) {
    if (board[y + dy[dir]][x + dx[dir]] == board[y][x]) {
      board[y + dy[dir]][x + dx[dir]] = board[y][x] * 2;
      board[y][x] = 0;

      maxNumber = max(maxNumber, board[y + dy[dir]][x + dx[dir]]);
    } else if (board[y + dy[dir]][x + dx[dir]] == 0) {
      board[y + dy[dir]][x + dx[dir]] = board[y][x];
      board[y][x] = 0;
    }
    x += dx[dir];
    y += dy[dir];
  }
}

void dfs(vector<vector<int> > board, int depth, int dir) {
  if (depth == 6) {
    return;
  }

  if (dir == 1 || dir == 2) {
    for (int y = 0; y < n; y++) {
      for (int x = 0; x < n; x++) {
        if (board[y][x] != 0) {
          move(x, y, dir, board);
        }
      }
    }
  } else if (dir == 0 || dir == 3) {
    for (int y = n - 1; y >= 0; y--) {
      for (int x = n - 1; x >= 0; x--) {
        if (board[y][x] != 0) {
          move(x, y, dir, board);
        }
      }
    }
  }

  for (int i = 0; i < 4; i++) {
    dfs(board, depth + 1, i);
  }
}

int main() {
  cin >> n;
  vector<vector<int> > board(n, vector<int>(n));

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      cin >> board[i][j];
      maxNumber = max(maxNumber, board[i][j]);
    }
  }

  dfs(board, 0, 4);
  cout << maxNumber << endl;

  return 0;
}

첫 실패 원인을 알아보니 한 라인을 중복으로 합치고 밀고 있었음 ex) 2 2 2 2 2 2 -> 4 0 4 0 4 0 -> 4 0 8 0 0 0 이런식으로 합치고 밀고 하고있었음. 그래서 합치고 미는 코드를 짜보니, 4군데 전부 해야하기 때문에 미는 dir, 합치는 dir이 달라져야 해서 코드 난독화가 발생.

그래서 board를 돌리면서 한 군데에서 밀고 합치는 코드를 작성하기로 함.

C++ 문제풀이

/* ************************************************************************** */
/*                                                                            */
/*                                                      :::    :::    :::     */
/*   Problem Number: 12100                             :+:    :+:      :+:    */
/*                                                    +:+    +:+        +:+   */
/*   By: chanhihi <boj.kr/u/chanhihi>                +#+    +#+          +#+  */
/*                                                  +#+      +#+        +#+   */
/*   https://boj.kr/12100                          #+#        #+#      #+#    */
/*   Solved: 2024/09/22 22:22:12 by chanhihi      ###          ###   ##.kr    */
/*                                                                            */
/* ************************************************************************** */

#include <algorithm>
#include <iostream>
#include <vector>

using namespace std;

int n;
int maxNumber = 0;

vector<int> cleanUP(vector<int> newLine, vector<int> oldLine) {
  int index = 0;

  for (int i = 0; i < n; i++) {
    if (oldLine[i] != 0) {
      newLine[index++] = oldLine[i];
    }
  }

  return newLine;
}

void addNumber(vector<int>& line) {
  for (int i = 0; i < n - 1; i++) {
    if (line[i] == line[i + 1] && line[i] != 0) {
      line[i] *= 2;
      line[i + 1] = 0;
      maxNumber = max(maxNumber, line[i]);
    }
  }
}

vector<int> mergeLine(vector<int> line) {
  vector<int> newLine(n, 0);
  newLine = cleanUP(newLine, line);
  addNumber(newLine);
  vector<int> finalLine(n, 0);
  return cleanUP(finalLine, newLine);
}

vector<vector<int>> moveLeft(vector<vector<int>> board) {
  for (int i = 0; i < n; i++) {
    board[i] = mergeLine(board[i]);
  }
  return board;
}

vector<vector<int>> rotateClockwise(vector<vector<int>> board) {
  vector<vector<int>> newBoard(n, vector<int>(n));
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      newBoard[j][n - 1 - i] = board[i][j];
    }
  }
  return newBoard;
}

void dfs(vector<vector<int>> board, int depth) {
  if (depth == 5) return;

  for (int i = 0; i < 4; i++) {
    vector<vector<int>> newBoard = moveLeft(board);
    dfs(newBoard, depth + 1);
    board = rotateClockwise(board);
  }
}

int main() {
  cin >> n;
  vector<vector<int>> board(n, vector<int>(n));

  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      cin >> board[i][j];
      maxNumber = max(maxNumber, board[i][j]);
    }
  }

  dfs(board, 0);

  cout << maxNumber << endl;

  return 0;
}

 

Swift 문제 풀이.

import Foundation

let n = Int(readLine()!)!
var board = [[Int]]()
var maxNumber = 0

for _ in 0..<n {
    let inputLine = readLine()!.split{$0==" "}.map { Int(String($0))! }
    board.append(inputLine)
    maxNumber = max(maxNumber, inputLine.max()!)
}

dfs(board, 0)

print(maxNumber)

func cleanUP(_ line: [Int]) -> [Int] {
    var newLine = [Int]()
    for num in line where num != 0 {
        newLine.append(num)
    }
    while newLine.count < n {
        newLine.append(0)
    }
    return newLine
}

func addNumber(_ line: inout [Int]) {
    for i in 0..<n - 1 {
        if line[i] == line[i + 1] && line[i] != 0 {
            line[i] *= 2
            line[i + 1] = 0
            maxNumber = max(maxNumber, line[i])
        }
    }
}

func mergeLine(_ line: [Int]) -> [Int] {
    var newLine = cleanUP(line)
    addNumber(&newLine)
    return cleanUP(newLine)
}

func moveLeft(_ board: [[Int]]) -> [[Int]] {
    var newBoard = board
    for i in 0..<n {
        newBoard[i] = mergeLine(board[i])
    }
    return newBoard
}

func rotateClockwise(_ board: [[Int]]) -> [[Int]] {
    var newBoard = Array(repeating: Array(repeating: 0, count: n), count: n)
    for i in 0..<n {
        for j in 0..<n {
            newBoard[j][n - 1 - i] = board[i][j]
        }
    }
    return newBoard
}

func dfs(_ board: [[Int]], _ depth: Int) {
    if depth == 5 { return }
    var board = board
    
    for _ in 0..<4 {
        let newBoard = moveLeft(board)
        dfs(newBoard, depth + 1)
        board = rotateClockwise(board)
    }
}

'🐣 > BOJ' 카테고리의 다른 글

1446 swift / c++ - 지름길  (0) 2024.10.04
18352 swift - 특정 거리의 도시 찾기  (0) 2024.10.02
6603 swift - 로또  (0) 2024.04.28
1946 swift - 신입 사원 / 시간 초과 해결  (0) 2024.03.10
14171 swift - Cities and States  (0) 2024.03.06