풀이

 

처음에는 이런 유형의 문제를 처음 봤기 때문에, 도형을 만들고, 각각 돌려서 확인을 해야 하는지, 어떻게 확인을 할 수 있을지 감이 안 왔다. 구현해보려고 끄적이다가 답이 도저히 안 나와서 구글링을 통해 약간의 힌트를 얻었다.

 

보니 각 도형들의 크기는 네개의 칸으로 구성되어 있고, 상하좌우로 이동했을 때 보라색 테트로미노를 뺀 네 개의 도형을 만들 수 있었다. 즉 dfs, bfs 문제의 응용 버전이었던 것이다.

 

본인은 bfs로 구현하였고, 맵의 각 위치마다 depth가 4개인 모든 도형을 만들어 합을 비교하였다.

n과 m은 최대 500칸이고, 칸마다 dfs로 구현했을 때 만들어지는 최대 가짓수는 4^3 보라색 테트로미노를 제외한 테트로미노를 모든 칸에서 만든다고 가정했을 때 500*500 *64 즉 완전 탐색을 하더라도 16,000,000 이므로 요구사항인 2초 안에 가능하다.

 

private static void dfs(int x, int y, int depth, int sum) {
   if (depth == 4) {
      max = Math.max(max, sum);
      return;
   }

   for (int i = 0; i < 4; i++) {
      int tx = dx[i] + x;
      int ty = dy[i] + y;
      if (tx < 0 || tx >= n || ty < 0 || ty >= m || visit[tx][ty]) {
         continue;
      }
      visit[tx][ty] = true;
      dfs(tx, ty, depth + 1, sum + map[tx][ty]);
      visit[tx][ty] = false;
   }
}

 

dfs는 다른 문제와 다를 거없이 방문하지 않았을 경우에 다른 칸으로 이동하여 depth가 4일 때까지 만들었다.

보라색 테트로미노는 두 번째 칸에서 두 개의 칸을 이동을 해야하지만, 그림과 같이 가운데를 중심을 두고 세 개를 갈 수 있다면 도형을 만드는 방식으로 만들었다.

 

private static void makePurple(int start, int x, int y, int depth, int sum) {
   if (depth == 4) {
      max = Math.max(max, sum);
      return;
   }

   for (int i = start; i < 4; i++) {
      int tx = dx[i] + x;
      int ty = dy[i] + y;
      if (tx < 0 || tx >= n || ty < 0 || ty >= m || visit[tx][ty]) {
         continue;
      }
      makePurple(i + 1, x, y, depth + 1, sum + map[tx][ty]);
   }
}

 

좌표 x,y는 가만히 두고, visit과 상관없이 start로 상하좌우를 순서대로 구현하면, 중복이 되지 않는다. 순차적인 조합, 중복되지 않는 조합을 할 때도 가끔 응용한다.

 

전체 풀이
import java.util.Scanner;

public class Main {

   private static int[] dx = {1, -1, 0, 0};
   private static int[] dy = {0, 0, 1, -1};
   private static int[][] map;
   private static boolean[][] visit;
   private static int n;
   private static int m;
   private static int max = 0;

   public static void main(String[] args) {
      Scanner s = new Scanner(System.in);
      n = s.nextInt();
      m = s.nextInt();
      map = new int[n][m];
      visit = new boolean[n][m];
      for (int i = 0; i < n; i++) {
         for (int j = 0; j < m; j++) {
            map[i][j] = s.nextInt();
         }
      }

      for (int i = 0; i < n; i++) {
         for (int j = 0; j < m; j++) {
            visit[i][j] = true;
            dfs(i, j, 1, map[i][j]);
            visit[i][j] = false;
            makePurple(0, i, j, 1, map[i][j]);
         }
      }
      System.out.println(max);
   }

   private static void makePurple(int start, int x, int y, int depth, int sum) {
      if (depth == 4) {
         max = Math.max(max, sum);
         return;
      }

      for (int i = start; i < 4; i++) {
         int tx = dx[i] + x;
         int ty = dy[i] + y;
         if (tx < 0 || tx >= n || ty < 0 || ty >= m || visit[tx][ty]) {
            continue;
         }
         makePurple(i + 1, x, y, depth + 1, sum + map[tx][ty]);
      }
   }

   private static void dfs(int x, int y, int depth, int sum) {
      if (depth == 4) {
         max = Math.max(max, sum);
         return;
      }

      for (int i = 0; i < 4; i++) {
         int tx = dx[i] + x;
         int ty = dy[i] + y;
         if (tx < 0 || tx >= n || ty < 0 || ty >= m || visit[tx][ty]) {
            continue;
         }
         visit[tx][ty] = true;
         dfs(tx, ty, depth + 1, sum + map[tx][ty]);
         visit[tx][ty] = false;

      }
   }
}

'CodingTest' 카테고리의 다른 글

[백준 14503번] JAVA 로봇 청소기  (0) 2022.12.05
[백준 1987번] JAVA 알파벳  (0) 2022.12.05
[백준 2293번] JAVA 동전 1  (0) 2022.12.02
[백준 15686번] JAVA 치킨 배달  (0) 2022.12.01
[백준 1759번] JAVA 암호 만들기  (0) 2022.12.01

+ Recent posts