코테적 감자/프로그래머스
[프로그래머스-java] Lv.3 경주로 건설
dreaming-potato
2024. 11. 13. 21:26
알고리즘 : BFS + DP
좌표에서 이동할 수 있는 4가지 방향에 대하여 저장하는 배열을 선언하여 DP+BFS를 진행.
문제 설명
https://school.programmers.co.kr/learn/courses/30/lessons/67259
프로그래머스
SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프
programmers.co.kr
😁내 풀이
처음에는 이전의 방향성을 유지해서, 최선의 선택을 내리도록 하게 알고리즘을 구상했다.
하지만 배열의 사이즈가 크지 않고, 4가지 방향성에 대해서 탐색을 진행해도 지장이 없을 것 같아서
좌표평면에 위치에 4가지 방향의 cost를 담는 배열을 선언해서 저장한 후 최종 위치의 4가지 방향값 중
최솟값을 return하게 작성했다.
나름 가독성이 괜찮지 않나?
✈️필요한 정보
기존의 BFS문제들과 다르게 이 문제에서는 따로 class로 선언하여 원하는 정보를 저장하는 객체를 큐에 넣어야했다.
x,y좌표 / 방향 / 해당 좌표까지 오기까지 방향성에 따른 cost
이 4가지 정보를 담고 있는 Loc class를 선언하여 사용했다.
🪟몇가지 고려해야 할 상황
- 대표적인 BFS 케이스 처럼 움직인 이후 좌표가 범위를 벗어나는 지 확인
- 움직일 수 있는 위치인지 확인
- 벽으로 막혀 있는지, 출발 지점인지
- Cost 계산
- 방향성이 이전과 같다면 +100
- 다르다면 코너돌기 +500 이동 +100 = 총 600 더하기
- ( 이 부분에서 500만 더해줘서 정답이 안나오길래 한참 해맸다 ㅜㅜ )
- 처음 시작점에서 시작하는 경우 무조건 100을 더하게 설정하였다.( 이 부분에서도 문제였음 )
- 제자리로 되돌아 오는 경우
- 아래 그림처럼 노란색 형광펜 경로를 따라 도착한 B에서 BFS를 진행하면 다시 A 방향으로 돌아간다.
- 여기서 A 방향으로 중복되어 경로를 갱신하는 부분을 생각해, A에서 B로 진행한 방향 - B에서 A로 진행한 방향을 뺏을 때 2가 나오면, 즉 서로 반대 방향을 의미하므로 단순하게 100으로 계산하였다.
- 이렇게 계산해도 되는 이유는 어처피 최종 도착지 기준으로는 이러한 반대 방향성으로 계산 되는 일이 없기 때문이다.
import java.util.*;
// 좌표, 방향, 현재까지 cost
class Loc {
int x;
int y;
int cost;
int dir;
public Loc (int x,int y,int cost,int dir){
this.x = x;
this.y = y;
this.cost = cost;
this.dir = dir ;
}
}
class Solution {
private static int N;
private static int[][][] dist;
// 방향
private static int[] dx = {-1,0,1,0};
private static int[] dy = {0,1,0,-1};
// 움직임이 좌표를 벗어나는 지 확인
private static boolean isOut(int nx,int ny){
return (nx < 0 || nx >=N || ny < 0 || ny >= N);
}
// 방향성에 따른 cost 계산
private static int calCost(int prevDir,int currentDir,int cost){
if ( prevDir == currentDir || Math.abs(prevDir - currentDir) == 2){
return cost+ 100;
}
else return cost + 600;
}
public int solution(int[][] board) {
// 보드의 크기 저장 및 초기화
N = board.length;
dist = new int[N+1][N+1][4];
ArrayDeque<Loc> q = new ArrayDeque<>();
// BFS 수행하면서 이전 방향 정보 바탕으로 갱신
q.offer(new Loc(0,0,0,-1));
while (!q.isEmpty()){
Loc cur = q.poll();
for (int dir = 0; dir < 4; dir++){
int nx = cur.x + dx[dir];
int ny = cur.y + dy[dir];
if(isOut(nx,ny)) continue;
if (board[nx][ny] != 0 || (nx == 0 && ny == 0)) continue;
int newCost = calCost(cur.dir,dir,cur.cost);
if (dist[nx][ny][dir] ==0 || dist[nx][ny][dir] > newCost){
if (cur.x == 0 && cur.y == 0 ){
newCost = 100;
}
dist[nx][ny][dir] = newCost;
q.offer(new Loc(nx,ny,newCost,dir));
}
}
}
int minum = Integer.MAX_VALUE;
for (int i: dist[N-1][N-1]){
if (i !=0) minum = Math.min(minum,i);
}
return minum;
}
}