[C++] 백준 14500 : 테스토미노

Kim Nahyeong·2022년 3월 28일
0

백준

목록 보기
125/157

#include <iostream>
#include <algorithm> // max
using namespace std;

int map[501][501]; // 0부터 시작
bool visited[501][501] = {false}; // 테스토미노

// 상하좌우 탐색
int dx[4] = {1, -1, 0, 0};
int dy[4] = {0, 0, 1, -1};

int Max = -1; // 최댓값

int N, M; // 세로, 가로

// ㅗㅜㅏㅓ는 DFS로 탐색 불가능
void testimony(int x, int y){ // x, y 는 가운데 좌표
  //세로 : x, 가로 : y, 조건문 잘 쓰기 모두 만족해야할 때는 &&

  //ㅗ
  if(x - 1 >= 0 && y - 1 >= 0 && y + 1 < M){
    Max = max(Max, map[x-1][y] + map[x][y-1] + map[x][y] + map[x][y+1]);
  }
  //ㅜ
  if(x + 1 < N && y - 1 >= 0 && y + 1 < M){
    Max = max(Max, map[x+1][y] + map[x][y] + map[x][y-1] + map[x][y+1]);
  }
  //ㅏ
  if(x - 1 >= 0 && x + 1 < N && y + 1 < M){
    Max = max(Max, map[x-1][y] + map[x+1][y] + map[x][y] + map[x][y+1]);
  }
  //ㅓ  
  if(x - 1 >= 0 && x + 1 < N && y - 1 >= 0){
    Max = max(Max, map[x-1][y] + map[x+1][y] + map[x][y] + map[x][y-1]);
  }

  return;
}

void DFS(int x, int y, int sum, int cnt){
  if(cnt == 4){ // 테스토미노 사각형 4개로 구성

    // printf("******\n");
    // for(int i=0; i<N; i++){
    //   for(int j=0; j<M; j++){
    //     printf("%d ", visited[i][j]);
    //   }
    //   printf("\n");
    // }
    
    // 시간 초과된 값 찾기 코드
    // int tmp = 0;
    // for(int i=0; i<N; i++){
    //   for(int j=0; j<M; j++){
    //     if(visited[i][j]){
    //       tmp += map[i][j]; // 테스토미노 값 찾기
    //     }
    //   }
    // }

    Max = max(Max, sum); // 최댓값 저장
    return;
  }

  for(int i = 0; i < 4; i++){
    int nx = x + dx[i];
    int ny = y + dy[i];

    if(nx < 0 || ny < 0 || nx >= N || ny >= M){
      continue; // 맵 초과시
    }

    if(!visited[nx][ny]){
      visited[nx][ny] = true;
      DFS(nx, ny, sum + map[nx][ny], cnt + 1);
      visited[nx][ny] = false; // 초기화
    }
  }
}

int main(){
  scanf("%d %d", &N, &M);

  for(int i=0; i<N; i++){
    for(int j=0; j<M; j++){
      scanf("%d", &map[i][j]); // 맵 입력받기
    }
  }

  for(int i=0; i<N; i++){
    for(int j=0; j<M; j++){
      visited[i][j] = true;
      DFS(i, j, map[i][j], 1); // 모든 시작점에 대해서 찾기
      testimony(i, j); // ㅗ 모양 찾기
      visited[i][j] = false; // 초기화
    }
  }

  printf("%d", Max); // 최댓값 출력

  return 0;
}
  • 원래 인접한 사각형으로 테스토미노가 이어지기 때문에 BFS를 사용하려고 했지만 브루트포스로 모든 경우의 값을 찾아야하기에 전역 큐를 사용하면 원하는대로 값이 잘 나오지 않았다. 때문에 DFS를 사용하게 되었다.

  • ㅗ,ㅜ,ㅓ,ㅏ 의 경우에는 DFS로 찾을 수 없다. 따라서 좌표를 직접 지정하여 해당 경우를 따로 찾아주어야한다. 이 때 조건을 잘 찾아야한다. 여기서 조건문을 잘못 세워서 꽤 틀렸다. x, y의 순서로 배열을 사용하면 세로가 x, 가로가 y가 된다. 헷갈리지 말자.

  • 값의 합을 DFS에서 구할때는 이것도 재귀 함수의 매개 변수로 넘겨주는 것이 for문으로 다시 탐색을 하는 것보다 시간이 적게 걸린다.

  • 모든 점에서 테스토미노의 시작점으로 두고 찾아야하기 때문에 브루트포스 알고리즘을 이용했다고 볼 수 있다. DFS에서 방문 여부를 사용하되 초기화 시켜야한다면 DFS 호출의 전 후 코드에 방문 여부를 체크하고 다시 초기화시켜주면 된다.

0개의 댓글