[프로그래머스 알고리즘 고득점 Kit][깊이/너비 우선 탐색(DFS/BFS)][Java] 아이템 줍기

2026. 4. 28. 01:21·알고리즘 & 자료구조/문제 풀이

https://school.programmers.co.kr/learn/courses/30/lessons/87694

 

프로그래머스

SW개발자를 위한 평가, 교육의 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프

programmers.co.kr

 

초기에 메서드도 분리하고 깔끔하게 쓰려고 분리할 거 다하다가
복잡해지고... 디버깅도 쉽지 않았다.


1. 복잡한 코드



일단 메인 아이디어는 주어진 사각형의 테두리를 남겨두고 bfs로 탐색하면서 거리를 업데이트 해주는 것이다.

주의했어야하는 부분은 expandedCordinate 메서드 위 주석에 나온 것처럼
1111
1111 이렇게 주어진 사각형 내부 공백이 없어서 테두리만 남길 수 없었기에
스케일을 키우는 작업을 했어야했습니다.

import java.util.*;

class Solution {

    int[][] expandedRectangle;
    int expandedCharacterX;
    int expandedCharacterY;
    int expandedItemX;
    int expandedItemY;
    final int SIZE = 105;
    int[][] map;
    int[][] dist;
    final int[] dx = {-1, 1, 0, 0};
    final int[] dy = {0, 0, -1, 1};
    
    public int solution(int[][] rectangle, int characterX, int characterY, int itemX, int itemY) {
        map = new int[SIZE][SIZE];
        dist = new int[SIZE][SIZE];
        
        expandCordinate(rectangle, characterX, characterY, itemX, itemY);
        clearInsideOfFrame(expandedRectangle);
        
        return bfs(expandedCharacterX, expandedCharacterY, expandedItemX, expandedItemY) / 2;
    }

    //1111
    //1111 이런 사각형이 있다고 생각하면 중간 공백이 없어서
    //테두리와 내부를 분리할 수 없음, 그래서 모든 좌표를 2배함으로써 중간 공백을 만들어줌
    public void expandCordinate(int[][] rectangle, int characterX, int characterY, int itemX, int itemY) {
        expandedRectangle = new int[rectangle.length][4];

        expandedCharacterX = 2 * characterX;
        expandedCharacterY = 2 * characterY;
        expandedItemX = 2 * itemX;
        expandedItemY = 2 * itemY;
        for(int i=0; i<rectangle.length; i++){
            expandedRectangle[i][0] = 2 * rectangle[i][0];
            expandedRectangle[i][1] = 2 * rectangle[i][1];
            expandedRectangle[i][2] = 2 * rectangle[i][2];
            expandedRectangle[i][3] = 2 * rectangle[i][3];
        }
    }
    public void fillRectangle(int[][] rectangle) {

        for(int[] r : rectangle) {
            fillMap(r[0], r[1], r[2], r[3], 1);
        }
    }
    public void clearInsideOfFrame(int[][] rectangle) {
        fillRectangle(rectangle);
        
        for(int[] r : rectangle) {
            fillMap(r[0]+1, r[1]+1, r[2]-1, r[3]-1, 0);
        }
    }
    public void fillMap(int x1, int y1, int x2, int y2, int fillNum) {
        for(int x=x1; x<=x2; x++) {
            for(int y= y1; y<=y2; y++) {
                map[x][y] = fillNum;
            }
        }
    }
    public int bfs(int startX, int startY, int targetX, int targetY) {
        for(int i=0; i<SIZE; i++) {
            Arrays.fill(dist[i], -1);
        }
        Queue<int[]> q = new ArrayDeque<>();
        q.add(new int[] {startX, startY});
        dist[startX][startY] = 0;
        while(!q.isEmpty()) {
            int[] curr = q.poll();
            int x = curr[0];
            int y = curr[1];
            
            if(x == targetX && y == targetY) return dist[x][y];
            
            for(int d=0; d<4; d++) {
                int nx = x + dx[d];
                int ny = y + dy[d];
                
                if(nx < 0 || nx >= SIZE || ny < 0 || ny >= SIZE) continue;
                if(map[nx][ny] == 0) continue;
                if(dist[nx][ny] != -1) continue;
                
                q.add(new int[] {nx, ny});
                dist[nx][ny] = dist[x][y] + 1;
            }
        }
        return -1;
    }
}


2. 지피티한테 클린하게 바꾸면 어떻게 되냐 물어봤을 때 코드



스케일을 키운 사각형 배열은 필요 없다고 생각하긴했는데
없으니 확실히 깔끔해졌네요
제 코드를 레퍼런스로 보냈으니 결과는 그렇게 큰 차이가 없다고 생각합니다.

import java.util.*;

class Solution {

    private static final int SIZE = 105;
    private static final int SCALE = 2;
    private static final int ROAD = 1;
    private static final int EMPTY = 0;

    private static final int[] dx = {-1, 1, 0, 0};
    private static final int[] dy = {0, 0, -1, 1};

    private final int[][] map = new int[SIZE][SIZE];

    public int solution(int[][] rectangle, int characterX, int characterY, int itemX, int itemY) {
        buildBorderMap(rectangle);

        int startX = scale(characterX);
        int startY = scale(characterY);
        int targetX = scale(itemX);
        int targetY = scale(itemY);

        return bfs(startX, startY, targetX, targetY) / SCALE;
    }

    private void buildBorderMap(int[][] rectangles) {
        paintAreas(rectangles);
        eraseInnerAreas(rectangles);
    }

    private void paintAreas(int[][] rectangles) {
        for (int[] r : rectangles) {
            fill(
                    scale(r[0]),
                    scale(r[1]),
                    scale(r[2]),
                    scale(r[3]),
                    ROAD
            );
        }
    }

    private void eraseInnerAreas(int[][] rectangles) {
        for (int[] r : rectangles) {
            fill(
                    scale(r[0]) + 1,
                    scale(r[1]) + 1,
                    scale(r[2]) - 1,
                    scale(r[3]) - 1,
                    EMPTY
            );
        }
    }

    private void fill(int x1, int y1, int x2, int y2, int value) {
        for (int x = x1; x <= x2; x++) {
            for (int y = y1; y <= y2; y++) {
                map[x][y] = value;
            }
        }
    }

    private int bfs(int startX, int startY, int targetX, int targetY) {
        int[][] dist = new int[SIZE][SIZE];

        for (int i = 0; i < SIZE; i++) {
            Arrays.fill(dist[i], -1);
        }

        Queue<int[]> queue = new ArrayDeque<>();
        queue.add(new int[]{startX, startY});
        dist[startX][startY] = 0;

        while (!queue.isEmpty()) {
            int[] current = queue.poll();
            int x = current[0];
            int y = current[1];

            if (x == targetX && y == targetY) {
                return dist[x][y];
            }

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

                if (isOutOfRange(nx, ny)) {
                    continue;
                }

                if (map[nx][ny] != ROAD) {
                    continue;
                }

                if (dist[nx][ny] != -1) {
                    continue;
                }

                dist[nx][ny] = dist[x][y] + 1;
                queue.add(new int[]{nx, ny});
            }
        }

        return -1;
    }

    private boolean isOutOfBounds(int x, int y) {
        return x < 0 || y < 0 || x >= SIZE || y >= SIZE;
    }

    private int scale(int value) {
        return value * SCALE;
    }
}

 

저작자표시 비영리 변경금지 (새창열림)

'알고리즘 & 자료구조 > 문제 풀이' 카테고리의 다른 글

[프로그래머스 알고리즘 고득점 Kit][깊이/너비 우선 탐색(DFS/BFS)][Java] 여행경로  (0) 2026.04.27
[LeetCode][Java][영어공부] 1071. Greatest Common Divisor of Strings  (0) 2026.04.24
[프로그래머스 알고리즘 고득점 Kit][스택/큐][Java] 기능 개발  (0) 2026.04.24
[프로그래머스 알고리즘 고득점 Kit][깊이/너비 우선 탐색(DFS/BFS)][Java] 단어 변환  (0) 2026.04.21
[프로그래머스 알고리즘 고득점 Kit][동적계획법(Dynamic Programming))][Java] N으로 표현  (0) 2026.04.19
'알고리즘 & 자료구조/문제 풀이' 카테고리의 다른 글
  • [프로그래머스 알고리즘 고득점 Kit][깊이/너비 우선 탐색(DFS/BFS)][Java] 여행경로
  • [LeetCode][Java][영어공부] 1071. Greatest Common Divisor of Strings
  • [프로그래머스 알고리즘 고득점 Kit][스택/큐][Java] 기능 개발
  • [프로그래머스 알고리즘 고득점 Kit][깊이/너비 우선 탐색(DFS/BFS)][Java] 단어 변환
수수다
수수다
우하하
  • 수수다
    그냥살자
    수수다
  • 전체
    오늘
    어제
    • 분류 전체보기 (53) N
      • 프로젝트 (1)
      • 알고리즘 & 자료구조 (27) N
        • 내용 정리 (2)
        • 문제 풀이 (25) N
      • 데이터베이스 (21)
        • 내용 정리 (1)
        • 문제 풀이 (20)
      • CS (2)
      • 기타 (2)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

    • 네이버 블로그
  • 공지사항

  • 인기 글

  • 태그

    그래프
    DP
    코테
    매개변수탐색
    coalesce
    알고리즘
    IFNULL
    바이브코딩
    Java
    싸피
    프로그래머스
    해시
    DisjointSet
    바킹독
    코딩테스트
    SSAFY
    유니온파인드
    이분탐색
    삼성청년SW·AI아카데미
    date_format
    HTTP 메서드
    분리집합
    평균회귀
    프로그래머스 알고리즘 고득점 kit
    동적계획법
    SQL
    깊이/너비 우선 탐색(DFS/BFS)
    코팅테스트
    mysql
    bfs
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
수수다
[프로그래머스 알고리즘 고득점 Kit][깊이/너비 우선 탐색(DFS/BFS)][Java] 아이템 줍기
상단으로

티스토리툴바