[level 3] [카카오 인턴] 경주로 건설 - 67259
성능 요약
메모리: 84.8 MB, 시간: 31.59 ms
구분
코딩테스트 연습 > 2020 카카오 인턴십
채점결과
정확성: 100.0
합계: 100.0 / 100.0
제출 일자
2024년 11월 26일 00:18:08
문제 설명
건설회사의 설계사인 죠르디
는 고객사로부터 자동차 경주로 건설에 필요한 견적을 의뢰받았습니다.
제공된 경주로 설계 도면에 따르면 경주로 부지는 N x N
크기의 정사각형 격자 형태이며 각 격자는 1 x 1
크기입니다.
설계 도면에는 각 격자의 칸은 0
또는 1
로 채워져 있으며, 0
은 칸이 비어 있음을 1
은 해당 칸이 벽으로 채워져 있음을 나타냅니다.
경주로의 출발점은 (0, 0) 칸(좌측 상단)이며, 도착점은 (N-1, N-1) 칸(우측 하단)입니다. 죠르디는 출발점인 (0, 0) 칸에서 출발한 자동차가 도착점인 (N-1, N-1) 칸까지 무사히 도달할 수 있게 중간에 끊기지 않도록 경주로를 건설해야 합니다.
경주로는 상, 하, 좌, 우로 인접한 두 빈 칸을 연결하여 건설할 수 있으며, 벽이 있는 칸에는 경주로를 건설할 수 없습니다.
이때, 인접한 두 빈 칸을 상하 또는 좌우로 연결한 경주로를 직선 도로
라고 합니다.
또한 두 직선 도로
가 서로 직각으로 만나는 지점을 코너
라고 부릅니다.
건설 비용을 계산해 보니 직선 도로
하나를 만들 때는 100원이 소요되며, 코너
를 하나 만들 때는 500원이 추가로 듭니다.
죠르디는 견적서 작성을 위해 경주로를 건설하는 데 필요한 최소 비용을 계산해야 합니다.
예를 들어, 아래 그림은 직선 도로
6개와 코너
4개로 구성된 임의의 경주로 예시이며, 건설 비용은 6 x 100 + 4 x 500 = 2600원 입니다.
또 다른 예로, 아래 그림은 직선 도로
4개와 코너
1개로 구성된 경주로이며, 건설 비용은 4 x 100 + 1 x 500 = 900원 입니다.
도면의 상태(0은 비어 있음, 1은 벽)을 나타내는 2차원 배열 board가 매개변수로 주어질 때, 경주로를 건설하는데 필요한 최소 비용을 return 하도록 solution 함수를 완성해주세요.
[제한사항]
- board는 2차원 정사각 배열로 배열의 크기는 3 이상 25 이하입니다.
- board 배열의 각 원소의 값은 0 또는 1 입니다.
- 도면의 가장 왼쪽 상단 좌표는 (0, 0)이며, 가장 우측 하단 좌표는 (N-1, N-1) 입니다.
- 원소의 값 0은 칸이 비어 있어 도로 연결이 가능함을 1은 칸이 벽으로 채워져 있어 도로 연결이 불가능함을 나타냅니다.
- board는 항상 출발점에서 도착점까지 경주로를 건설할 수 있는 형태로 주어집니다.
- 출발점과 도착점 칸의 원소의 값은 항상 0으로 주어집니다.
입출력 예
board | result |
---|---|
[[0,0,0],[0,0,0],[0,0,0]] | 900 |
[[0,0,0,0,0,0,0,1],[0,0,0,0,0,0,0,0],[0,0,0,0,0,1,0,0],[0,0,0,0,1,0,0,0],[0,0,0,1,0,0,0,1],[0,0,1,0,0,0,1,0],[0,1,0,0,0,1,0,0],[1,0,0,0,0,0,0,0]] | 3800 |
[[0,0,1,0],[0,0,0,0],[0,1,0,1],[1,0,0,0]] | 2100 |
[[0,0,0,0,0,0],[0,1,1,1,1,0],[0,0,1,0,0,0],[1,0,0,1,0,1],[0,1,0,0,0,1],[0,0,0,0,0,0]] | 3200 |
입출력 예에 대한 설명
입출력 예 #1
본문의 예시와 같습니다.
입출력 예 #2
위와 같이 경주로를 건설하면 직선 도로
18개, 코너
4개로 총 3800원이 듭니다.
입출력 예 #3
위와 같이 경주로를 건설하면 직선 도로
6개, 코너
3개로 총 2100원이 듭니다.
입출력 예 #4
붉은색 경로와 같이 경주로를 건설하면 직선 도로
12개, 코너
4개로 총 3200원이 듭니다.
만약, 파란색 경로와 같이 경주로를 건설한다면 직선 도로
10개, 코너
5개로 총 3500원이 들며, 더 많은 비용이 듭니다.
※ 공지 - 2021년 8월 30일 테스트케이스가 추가되었습니다.
출처: 프로그래머스 코딩 테스트 연습, https://school.programmers.co.kr/learn/challenges
제출 코드
최단 경로를 구하기 위해 bfs 탐색을 이용한다.
같은 지점을 탐색할 때,
1. 이미 저장된 cost의 다음 cost 최댓값( = 저장된 cost + 100 + 500)
2. 현재 cost 다음 cost 최솟값(= 현재 cost + 100)
1과 2를 비교하였을 때 2가 더 크거나 같으면 더 탐색할 필요가 없다.
이때는 탐색을 건너 뛰어 탐색 횟수를 줄일 수 있다.
import java.util.*;
class Solution {
int[][] d = {{0,1}, {1,0}, {0,-1}, {-1,0}}; //{x,y}
int answer = Integer.MAX_VALUE;
int n; // N
int[][] map; // 도면
int[][] visited; // 방문한 길 최소 cost
int bfs(){
// path : {x, y, dx, dy, cost}. cost가 작은 것부터 Dequeue.
Queue<int[]> path = new LinkedList<>();
path.offer(new int[] {0,0,0,0,0}); // pat에 출발지 add
int x, y, cost;
while(!path.isEmpty()){
int[] cur = path.poll();
// 도착지에 도달하면 cost return
if(cur[0] == n && cur[1] == n){
answer = Math.min(cur[4], answer);
}
// 방문한 적 있는데 현재 cost가 더 클 때 continue;
if(visited[cur[0]][cur[1]] != 0 && visited[cur[0]][cur[1]]+600 <= cur[4]+100){
continue;
}
visited[cur[0]][cur[1]] = cur[4]; // 방문 표시
cost = cur[4] + 100;
for(int i = 0; i<4; i++){
x = cur[0] + d[i][0];
y = cur[1] + d[i][1];
// 갈 수 없는 위치이면 continue;
if(x<0|| x>n || y<0 || y>n || map[x][y] == 1){
continue;
}
// path에 경로 담기. 방향 꺾으면 코너 비용 추가
if((cur[2]==0&&cur[3]==0)||(d[i][0]==cur[2]&&d[i][1]==cur[3])){
path.offer(new int[] {x, y, d[i][0], d[i][1], cost});
}else{
path.offer(new int[] {x, y, d[i][0], d[i][1], cost+500});
}
}
}
return 0;
}
public int solution(int[][] board) {
map = board;
n = board.length -1;
visited = new int[n+1][n+1];
bfs();
return answer;
}
}
'코딩 테스트 정복기 > 프로그래머스' 카테고리의 다른 글
[프로그래머스/level 2] N-Queen - 12952 (0) | 2024.12.05 |
---|---|
[프로그래머스/level 2] 전력망을 둘로 나누기 - 86971 (0) | 2024.12.04 |
[프로그래머스/level 2] 미로 탈출 - 159993 (0) | 2024.11.25 |
[프로그래머스/level 2] 게임 맵 최단거리 - 1844 (1) | 2024.11.24 |
[프로그래머스/level 3] 섬 연결하기 - 42861 (0) | 2024.11.19 |