developer-ellen
인간 디버거의 로그 찍기
developer-ellen
전체 방문자
오늘
어제
  • 분류 전체보기 (217)
    • 회고록 (0)
    • 취뽀 및 커리어 여정의 Stack (2)
      • SSAFY 7기 (2)
    • 프로그래밍공부 (24)
      • c++ (0)
      • JAVA (3)
      • Spring (5)
      • design pattern (3)
      • BackDB (1)
      • Servlet&JSP (3)
      • Vue (4)
      • JPA (4)
      • Infra (1)
      • Linux (0)
    • AI (3)
      • papers (3)
      • trend (0)
    • 프로젝트진행 (0)
      • 데이터베이스 (0)
      • 서버개발 (0)
      • 인공지능 (0)
      • 하루정리 (0)
    • 포트폴리오 (0)
    • 알고리즘 (158)
      • 알고리즘문풀 (155)
      • 알고리즘공부 (3)
    • 통계공부 (15)
      • 시계열분석 (15)
      • 회귀분석 (0)
    • CS (14)
      • 컴퓨터네트워크 (4)
      • 운영체제 (8)
      • 데이터베이스 (2)
    • 주저리주저리 (0)
      • 필사 (0)
    • 취업관련정보 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 코테파이썬
  • Arima
  • 삼성코테준비
  • 삼성코테파이썬준비
  • 삼성코테자바준비
  • AR모형
  • 삼성코테기출자바풀이
  • MA모형
  • 카카오코테
  • 삼성코테파이썬
  • SW역량테스트파이썬풀이
  • BOJ파이썬풀이
  • 백준파이썬풀이
  • 삼성코테구현풀이
  • 데이터분석
  • c++ 빌더 패턴
  • 통계학
  • 운영체제인터럽트
  • ARIMA모형
  • 시계열
  • 삼성코테파이썬풀이
  • c++디자인패턴
  • 삼성코테자바꿀팁
  • 카카오코테java풀이
  • 통계분석
  • 삼성코테구현문제추천
  • 삼성코테기출
  • 삼성코테자바풀이
  • SW역량테스트파이썬
  • 시계열분석

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
developer-ellen

인간 디버거의 로그 찍기

알고리즘/알고리즘문풀

BOJ - 거울 설치 2151번 (JAVA)

2022. 7. 15. 00:01

❓ 문제 - 백준 거울 설치 2151번 - JAVA 풀이법

 

출처 

(https://www.acmicpc.net/problem/2151)

 

2151번: 거울 설치

첫째 줄에 집의 크기 N (2 ≤ N ≤ 50)이 주어진다. 다음 N개의 줄에는 N개의 문자로 집에 대한 정보가 주어진다. ‘#’는 문이 설치된 곳으로 항상 두 곳이며, ‘.’은 아무 것도 없는 것으로 빛은

www.acmicpc.net

 

 

 

📝 문제해결법

1. 문제 해석

  • 하나의 문(#)에서 출발하여 다른 문(#)까지 도착할 수 있게 이동할 수 있어야 한다.
  • 거울(!)을 설치할 수 있는 위치에서 거울을 설치하면 45도 방향으로 이동 방향을 바꿀 수 있다.
  • 거울을 최소한 설치해서 하나의 문에서 다른문 까지 도착할 수 있도록 할 때, 최소 설치 거울의 갯수를 구하여라.

 

2. 이 문제는 BFS(너비 우선 탐색)으로 해결하였습니다.

  • Node는 위치 x, y ,현재 이동방향 dir, 설치한 거울 수 cnt로 나타낸다.
  • 두 문(#) 중 하나의 문에서 BFS를 하도록 하며, 큐에서 4방향(북,남,서,동)으로 이동할 수 있게 넣어준다.
  • visited는 방문체크 배열인데 큐에서 이동하면서 해당 위치(x,y)와 방향(dir)에 맞춰 현재까지 설치한 거울 수를 배열에 저장한다.
  • 큐에서 너비우선탐색으로 진행하며, 이동할 방향(nx, ny)의 범위가 가능한지, 벽이 아닌지, 이동하려는 방향에 설치한 거울 수가 더 적은 상태로 이미  방문을 했는지를 체크해준 후 continue 처리한다.
  • 만약 이동할 곳이 빈 곳(.) 이라면 현재 이동방향 그대로 큐에 넣어 이동처리한다.
  • 만약 이동할 곳이 거울이 설치할 수 있는 위치(!) 라면 거울을 설치 안 하고 지나가는 경우, 거울을 설치하고 지나가는 경우로 나눈다.
    • 거울을 설치할 때 현재 진행 방향이 북, 남이면 45도로 방향을 변경할 수 있으므로  동, 서로 방향을 바꿀 수 있다.
    • 거울을 설치할 때 현재 진행 방향이 동, 서이면 45도로 방향을 변경할 수 있으므로 북, 남으로 방향을 바꿀 수 있다.
  • 만약 이동할 곳이 문(#)이면 도착이므로 현재 이동할 때까지 설치한 거울 수의 최솟값을 갱신한다.

 

3. 느낀점 & 삽질

1) visited를 boolean으로 그냥 그 위치와 방향에 방문 했으면 방문하지 못하도록 구현했으나..

20
#.....!.!...........
******.*.***********
*!....!*.***********
*.****.*.***********
*.**!.!*.***********
*.**.***.***********
*.**!.!*.***********
*.****.*.***********
*.**!.!*.***********
*.**.***.***********
*!..!.......#*******
********.***.*******
********.***.*******
********.***.*******
********.***.*******
********.*!.!*******
********.*.*********
********.*!.!*******
********.***.*******
********!...!*******

와 같은 테케에서 답이 4가 나와야 하는데 7이 나왔다.

 

알고보니 큐에 먼저 설치한 거울 수가 많은 노드가 먼저 들어가서 방문처리 되었는데, 큐에 뒤에 있는 노드가 위치와 방향이 같은데 설치한 거울 수가 더 적으면 이미 방문처리 되어 큐에 들어가지 못해 최솟값에 영향을 준다.

 

따라서 int 배열로 바꿔 방문체크를 하였고, 배열 안에 현재 위치, 방향으로 이동까지 설치한 에어컨의 수보다 내가 지금 이동 하면서 설치한 에어컨의 수가 적을 때만 방문할 수 있도록 로직을 바꾸었고 잘 작동하였다.

 

2) BFS 문제의 경우 이런 큐에 먼저들어가고 방문처리와 관련해서 많은 문제들이 존재하는데

이런 부분까지 조심해서 로직을 구현해야겠다고 생각했다...

 

오랜만에 BFS를 푸니 재밌다....!

 

 

 

💻 소스코드 (JAVA)

// BOJ - 거울설치(2151번)
// BFS
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;

public class Main_2151 {
    public static int n;
    public static int min_value;
    public static class Node {
        int x;
        int y;
        int dir;
        int cnt;
        public Node(int x, int y, int dir, int cnt){
            this.x = x;
            this.y = y;
            this.dir = dir;
            this.cnt = cnt;
        }
    }
    public static int sx, sy;
    // 하, 상, 좌, 우
    public static int[] dx = {-1, 1, 0, 0};
    public static int[] dy = {0, 0, -1, 1};
    public static char[][] map;
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        n = Integer.parseInt(br.readLine());
        map = new char[n][n];

        for(int i=0;i<n;i++){
            map[i] = br.readLine().toCharArray();
            for(int j=0;j<n;j++){
                if(map[i][j] == '#'){
                    sx = i;
                    sy = j;
                }
            }
        }
        min_value = Integer.MAX_VALUE;
        bfs();
        System.out.println(min_value);
    }

    public static void bfs(){
        int[][][] visited = new int[n][n][4];
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                Arrays.fill(visited[i][j], Integer.MAX_VALUE);
            }
        }

        Queue<Node> q = new LinkedList<>();
        q.add(new Node(sx, sy, 0, 0));
        q.add(new Node(sx, sy, 1, 0));
        q.add(new Node(sx, sy, 2, 0));
        q.add(new Node(sx, sy, 3, 0));
        visited[sx][sy][0] = 0;
        visited[sx][sy][1] = 0;
        visited[sx][sy][2] = 0;
        visited[sx][sy][3] = 0;

        while (!q.isEmpty()){
            int q_len = q.size();
            for(int i=0;i<q_len;i++){
                Node node = q.poll();
                int nx = node.x + dx[node.dir];
                int ny = node.y + dy[node.dir];
                if(nx < 0 || nx >= n || ny < 0 || ny >= n || visited[nx][ny][node.dir] < node.cnt || map[nx][ny] == '*') continue;

                if(map[nx][ny] == '.'){
                    visited[nx][ny][node.dir] = node.cnt;
                    q.add(new Node(nx, ny, node.dir, node.cnt));
                } else if(map[nx][ny] == '!'){
                    visited[nx][ny][node.dir] = node.cnt;
                    if(node.dir <= 1){
                        visited[nx][ny][2] = node.cnt;
                        visited[nx][ny][3] = node.cnt;
                        q.add(new Node(nx, ny, node.dir, node.cnt));
                        q.add(new Node(nx, ny, 2, node.cnt+1));
                        q.add(new Node(nx, ny, 3, node.cnt+1));
                    } else {
                        visited[nx][ny][0] = node.cnt;
                        visited[nx][ny][1] = node.cnt;
                        q.add(new Node(nx, ny, node.dir, node.cnt));
                        q.add(new Node(nx, ny, 0, node.cnt+1));
                        q.add(new Node(nx, ny, 1, node.cnt+1));
                    }
                } else if(map[nx][ny] == '#'){
                    min_value = Math.min(min_value, node.cnt);
                }

            }
        }

    }
}

'알고리즘 > 알고리즘문풀' 카테고리의 다른 글

BOJ - 달빛 여우 16118번 (JAVA)  (1) 2022.07.17
BOJ - 후위 표기식 1918번 (JAVA)  (0) 2022.07.15
BOJ - 텔레포트3 12908번 (JAVA)  (0) 2022.07.13
프로그래머스 코딩테스트 고득점 Kit - 기능개발 (JAVA)  (0) 2022.07.08
BOJ - 열쇠 9328번 (JAVA)  (0) 2022.06.30
    '알고리즘/알고리즘문풀' 카테고리의 다른 글
    • BOJ - 달빛 여우 16118번 (JAVA)
    • BOJ - 후위 표기식 1918번 (JAVA)
    • BOJ - 텔레포트3 12908번 (JAVA)
    • 프로그래머스 코딩테스트 고득점 Kit - 기능개발 (JAVA)
    developer-ellen
    developer-ellen

    티스토리툴바