코딩테스트/백준

145000번 테트로미노

Cadi 2025. 10. 6. 20:06

코딩테스트 :  145000번 테트로미노 

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.

  • 정사각형은 서로 겹치면 안 된다.
  • 도형은 모두 연결되어 있어야 한다.
  • 정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.

정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.

아름이는 크기가 N×M인 종이 위에 테트로미노 하나를 놓으려고 한다. 종이는 1×1 크기의 칸으로 나누어져 있으며, 각각의 칸에는 정수가 하나 쓰여 있다.

테트로미노 하나를 적절히 놓아서 테트로미노가 놓인 칸에 쓰여 있는 수들의 합을 최대로 하는 프로그램을 작성하시오.

테트로미노는 반드시 한 정사각형이 정확히 하나의 칸을 포함하도록 놓아야 하며, 회전이나 대칭을 시켜도 된다.

입력

첫째 줄에 종이의 세로 크기 N과 가로 크기 M이 주어진다. (4 ≤ N, M ≤ 500)

둘째 줄부터 N개의 줄에 종이에 쓰여 있는 수가 주어진다. i번째 줄의 j번째 수는 위에서부터 i번째 칸, 왼쪽에서부터 j번째 칸에 쓰여 있는 수이다. 입력으로 주어지는 수는 1,000을 넘지 않는 자연수이다.

출력

첫째 줄에 테트로미노가 놓인 칸에 쓰인 수들의 합의 최댓값을 출력한다.

public class BackJoon
{
    private static int N;
    private static int M;
    public static int max = int.MinValue;
    public static int[,] matrix;

    // 상 하 좌 우
    public static int[] dr = new int[4] { -1, 1, 0, 0 };
    public static int[] dc = new int[4] { 0, 0, -1, 1 };
   public static void Main()
   {
       int[] NM = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
       N = NM[0];
       M = NM[1];

       matrix = new int[N, M];
       for (int i = 0; i < N; i++)
       {
           int[] row = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
           for (int j = 0; j < M; j++)
           {
               matrix [i,j] = row[j];
           }
       }

       for (int i = 0; i < N; i++)
       {
           for (int j = 0; j < M; j++)
           {
               bool[,] visited = new bool[N, M];
               DFS((i,j),0,0,visited);
           }
       }

       Console.WriteLine(max);
   }


   public static void DFS((int,int) pos ,int current,int count, bool[,] visited)
   {
       if (count >= 4)
       {
           if (current > max) max = current;
           return;
       }

       for (int i = 0; i < 4; i++)
       {
           int nextRow = pos.Item1 + dr [i];
           int nextCol = pos.Item2 + dc [i];

           if (nextRow >= 0 && nextRow < N && nextCol >= 0 && nextCol < M && !visited[nextRow, nextCol])
           {
               visited [nextRow, nextCol] = true;
               // 다음 카운트를 미리 더해줫음
               DFS ((nextRow,nextCol),current + matrix[nextRow,nextCol], count + 1, visited);
               visited [nextRow, nextCol] = false;
           }
       }
       
   }
}

 

처음에는 아래와 같은 조건을 보고 그냥 DFS만으로 풀면 되겠는데 ? 라고 생각했다.

폴리오미노란 크기가 1×1인 정사각형을 여러 개 이어서 붙인 도형이며, 다음과 같은 조건을 만족해야 한다.

정사각형은 서로 겹치면 안 된다.
도형은 모두 연결되어 있어야 한다.
정사각형의 변끼리 연결되어 있어야 한다. 즉, 꼭짓점과 꼭짓점만 맞닿아 있으면 안 된다.
정사각형 4개를 이어 붙인 폴리오미노는 테트로미노라고 하며, 다음과 같은 5가지가 있다.

4개를 이어붙인 것이니까 , 4번 DFS를 반복해 이어 붙인 후 그 칸들이 차지하는 점수를 더해주자 ! 라는 생각으로 풀었다.

다만, 메모리 초과 ( new visited[,]를 계속 사용해서 ) 가 났고, 그 문제를 고치고 난 후에는 틀리는 문제가 발생했다.

 

다시 생각해보니, 다른 모양은 모두 괜찮지만 뫼 산 모양 ( ㅗ ㅏ ㅓ ㅜ ) 모양은 , 현재 칸에서 한 칸씩 더해가는 모양으로는 풀 수 없었다. 하나의 꼭짓점에서 중간 꼭짓점을 들리지 않고는 다른 곳으로 갈 수 없기 때문이다. 따라서 뫼 산 모양만 따로 체크해주는 함수를 만들었다. 

using System.ComponentModel.Design;

public class BackJoon
{
    private static int N;
    private static int M;
    public static int max = int.MinValue;
    public static int[,] matrix;
    public static bool[,] visited;

    // 상 하 좌 우
    public static int[] dr = new int[4] { -1, 1, 0, 0 };
    public static int[] dc = new int[4] { 0, 0, -1, 1 };
    
    // row , col 기준으로 4개 좌표 ㅗ ㅜ ㅏ ㅓ 항상 왼쪽부터 위에부터
    private static int[,] mountainRow = new int[4, 4]
        { { 0, -1, 0, 0 }, { 0, 0, 1, 0 }, { -1, 0, 1, 0 }, { 0, -1, 0, 1 } };

    private static int[,] mountainCol = new int[4, 4]
    {
        { -1, 0, 0, 1 }, { -1, 0, 0, 1 }, { 0, 0, 0, 1 }, { -1, 0, 0, 0 }
    };
   public static void Main()
   {
       int[] NM = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
       N = NM[0];
       M = NM[1];

       matrix = new int[N, M];
       visited = new bool[N, M];
       for (int i = 0; i < N; i++)
       {
           int[] row = Console.ReadLine().Split(' ').Select(int.Parse).ToArray();
           for (int j = 0; j < M; j++)
           {
               matrix [i,j] = row[j];
           }
       }

       for (int i = 0; i < N; i++)
       {
           for (int j = 0; j < M; j++)
           {
               visited[i, j] = true;
               DFS((i,j),0,0,visited);
               visited[i, j] = false;
               CheckMountain(i,j);
           }
       }
       Console.WriteLine(max);
   }


   public static void DFS((int,int) pos ,int current,int count, bool[,] visited)
   {
       if (count >= 4)
       {
           if (current > max) max = current;
           return;
       }

       for (int i = 0; i < 4; i++)
       {
           int nextRow = pos.Item1 + dr [i];
           int nextCol = pos.Item2 + dc [i];

           if (nextRow >= 0 && nextRow < N && nextCol >= 0 && nextCol < M && !visited[nextRow, nextCol])
           {
               visited [nextRow, nextCol] = true;
               // 다음 카운트를 미리 더해줫음
               DFS ((nextRow,nextCol),current + matrix[nextRow,nextCol], count + 1, visited);
               visited [nextRow, nextCol] = false;
           }
       }
   }

   public static void CheckMountain(int row , int col)
   {
       List<(int,int)> mountain = new List<(int,int)>();

       for (int i = 0; i < 4; i++)
       {

           mountain.Clear();
           for (int j = 0; j < 4; j++)
           {
               int nextRow = row + mountainRow[i, j];
               int nextCol = col + mountainCol[i, j];
               if (nextRow >= 0 && nextRow < N && nextCol >= 0 && nextCol < M)
               {
                   mountain.Add((nextRow,nextCol));
               }
               else break;

               if (j == 3)
               {
                   int maxNum = 0; 
                   foreach ((int, int) mount in mountain)
                   {
                       maxNum += matrix[mount.Item1, mount.Item2];
                   }
                   if (maxNum > max) max = maxNum;
               }
           }
       }

     
   }
}

'코딩테스트 > 백준' 카테고리의 다른 글

17837번 새로운 게임 2  (0) 2025.10.15
17144번 미세먼지 안녕!  (0) 2025.10.07
17070번 파이프 옮기기 1  (0) 2025.09.26
23288번 주사위 굴리기 2  (0) 2025.09.24
20057번 마법사 상어와 토네이도  (0) 2025.09.19