BaekJoon

Geometry - 9715

wny0320 2025. 9. 17. 12:02

문제 설명

  1. 테스트 케이스 T가 주어진다.
  2. 테스트 케이스별로 가로 세로의 블럭 수를 C와 R로 주어진다.
  3. C*R의 갯수만큼 블럭이 각각 칸에 몇 개가 쌓여있는지 주어진다.
  4. 블럭에 가려지지 않은 보이는 면을 모두 구하여 출력한다.

주의사항

  1. 블럭에 가려진 면만 뺀다.
  2. 다시 말해서 바닥면은 가려진 것으로 치지 않는다.

문제 풀이

가로 세로의 갯수만큼 입력을 받은 후 블럭끼리 가려진 면을 빼는 문제이다.

기하학에 구현의 알고리즘으로 바로 구현하였다.

 

우선 위 예시 입력을 통해 설명해보겠다.

4231
2101
0001

여기서 1,1 인덱스인 1의 경우를 살펴보겠다

우선 1개의 블럭이므로 총 면의 수는 1*4 + 2로 총 6면을 가지고 있다.

 

그리고 이웃 면들을 검사해보자.

이웃면이 0,1 인덱스의 2개 블럭, 1,0 인덱스의 2개 블럭이 존재한다.

하지만 1,1 인덱스의 1개 블럭밖에 없으므로 해당 면들에 의해 1개씩 가려진다.

따라서 6 - 2로 4면을 가지게 된다.

 

코드는 이런식으로 모든 블럭이 이웃면이 있는지 검사해서 이웃면에 의해 가려진 면의 갯수만큼 빼주는 방식으로 계산하였다.

코드  풀이

using System;
using System.Collections.Generic;
using System.Linq;

namespace StudyCS
{
    class Program
    {
        public static void Main(string[] args)
        {
            int T = int.Parse(Console.ReadLine());
            int[] result = new int[T];
            for (int i = 0; i < T; i++)
            {
                int[] input = Array.ConvertAll(Console.ReadLine().Split(), int.Parse);
                int R = input[0];
                int C = input[1];

                List<List<int>> data = new List<List<int>>();
                for (int j = 0; j < R; j++)
                {
                    string input2 = Console.ReadLine();
                    List<int> temp = new List<int>();
                    for (int k = 0; k < C; k++)
                    {
                        temp.Add(int.Parse(input2[k].ToString()));
                    }
                    data.Add(temp);
                }
                result[i] += SeachNearSurface(ref data);
            }
            for (int i = 0; i < result.Length; i++)
            {
                Console.WriteLine(result[i]);
            }
        }
        public static int SeachNearSurface(ref List<List<int>> inData)
        {
            int result = 0;
            for (int i = 0; i < inData.Count; i++)
            {
                for(int j = 0; j < inData[i].Count; j++)
                {
                    if(inData[i][j] == 0)
                    {
                        continue;
                    }
                    int origin = inData[i][j] * 4 + 2;
                    if(i-1 > -1)
                    {
                        origin -= Math.Min(inData[i - 1][j], inData[i][j]);
                    }
                    if(i+1 < inData.Count)
                    {
                        origin -= Math.Min(inData[i + 1][j], inData[i][j]);
                    }
                    if(j-1 > -1)
                    {
                        origin -= Math.Min(inData[i][j - 1], inData[i][j]);
                    }
                    if(j+1 < inData[i].Count)
                    {
                        origin -= Math.Min(inData[i][j + 1], inData[i][j]);
                    }
                    result += origin;
                }
            }
            return result;
        }
    }
}

위에서 말한 부분을 코드로 작성한 것이다.

현재 면이 0이라면 블럭이 없기 때문에 넘어가고 블럭이 있다면 주변 블럭들을 탐색해서 원래 면에서 빼준다.

그 값을 결과값에 추가해서 한 번에 출력한다.

'BaekJoon' 카테고리의 다른 글

Greedy - 15748  (0) 2025.09.16
Dynamic Programming - 11060  (0) 2025.09.12
Dynamic Programming - 11053  (0) 2025.09.11
BFS - 18352  (0) 2025.09.10
백트래킹 - 4251  (0) 2025.09.09