문제 Lv.1 공원 산책 (방향 탐색 시뮬레이션)
: 지나다니는 길 O 장애물 X
["방향거리", "방향거리"..]
"E 5" = 현재 위치에서 동쪽으로 5칸 이동했다는 의미
공원의 가로 길이가 W, 세로 길이가 H
공원을 나타내는 문자열 배열 park
명령이 담긴 문자열 배열 routes
- 3 ≤ park[i]의 길이 ≤ 50
- S : 시작 지점 (1개)
- O : 이동 가능한 통로
- X : 장애물
- 1 ≤ routes의 길이 ≤ 50
- 수행할 명령어
- routes의 원소는 "op n"과 같은 구조 (op는 이동할 방향, n은 이동할 칸의 수)
- N : 북 이동 / S : 남 이동 / W : 서 이동 / E : 동 이동
- 1 ≤ n ≤ 9
[과정]
- 2차원 배열 헷갈리지 말자!! -
arr[행][열] 발음하는 순서대로 생각하면 된다 (행의 인덱스 / 열의 인덱스)
- 다만 행 인덱스는 세로줄을 보고 판단 열의 인덱스는 가로줄을 보고 판단
- 행의 개수 = 세로로 나열된 원소의 개수
열의 개수 = 가로로 나열된 원소의 개수
단순히 행은 가로줄을 의미하니까 가로줄의 원소의 개수와 같다고 생각해선 안된다!
x이동과 y이동은 좌표가 아닌 배열의 형식으로 생각한다
char[][] arr = {
{'O', 'S', 'O'},
{'O', 'X', 'O'},
{'O', 'O', 'O'}
};
여기서 S의 위치는 좌표형식으로 본다면 높이가 바뀐 것이 아니기 때문에 (1,0) 이다
하지만 배열의 형식으로 본다면 0번째 행의 1번째 열이므로 arr[1][0]이 맞다
고로 x를 가로의 이동이 아닌 행의 이동 (세로이동)으로 생각하고
y를 세로의 이동이 아닌 열의 이동 (가로이동)으로 생각한다
1. 좌표이동
- E = 우로 이동 = 열 변경 (y++)
- W = 좌로 이동 = 열 변경 (y--)
- N = 상으로 이동 = 행 변경 (x--)
- S = 하로 이동 = 행 변경 (x++)
2. 보통의 if문 조건과는 다르다
- 보통은 모두 될 조건문부터 먼저 쓴다 (&&연산자 사용)
- 하지만 해당코드는 참이 되지 않는 경우부터 먼저 쓴다 (||연산자 사용)
- nx < 0 || ny < 0 범위를 벗어날 경우
- ny >= park[0].length() || nx >= park.length 범위를 벗어날 경우
- || arr[nx][ny] == 'X' 장애물일 경우
- 위와 같을 경우 이동불가하므로 현재지점을 시작지점으로 다시 초기화 한다
nx,ny = 현지점 sx,sy = 시작지점 - break 하고 바로 종료 애초에 시작불가
3. 마지막 연산에서만 시작지점 갱신
- 명령문 [E 2]라고 해도 한번에 두칸을 가는게 아니라 한칸씩 가보면서 장애물이 있는지 확인 필요
- 가는길에 장애물이 없다면 마지막 순간에만 갱신하면 된다
- 예로 [E 2] 이면 1칸 이동했을 때는 시작지점을 갱신하지 않고 2칸 모두 다 이동했을 때만 시작지점을 현지점으로 갱신
[코드]
import java.io.*;
import java.util.*;
class Solution {
public int[] solution(String[] park, String[] routes) {
char arr[][] = new char[park.length][park[0].length()];
int result[] =new int[2];
int sx = 0;
int sy = 0;
for(int i=0;i<park.length; i++){
arr[i]=park[i].toCharArray();
for(int j=0; j<park[0].length();j++){
if(arr[i][j]=='S'){
sx=i;
sy=j;
}
}
}
for(String route : routes){
String dir = route.split(" ")[0];
int move = Integer.parseInt(route.split(" ")[1]);
int nx = sx;
int ny = sy;
for(int j=0; j<move; j++){
switch(dir){
case "E": ny++; break;
case "W": ny--; break;
case "N": nx--; break;
case "S": nx++; break;
}
if (nx < 0 || ny >= park[0].length() || ny < 0 || nx >= park.length || arr[nx][ny] == 'X') {
nx = sx;
ny = sy;
break;
}
if (j == move - 1) {
sx = nx;
sy = ny;
}
}
}
result[0] = sx;
result[1] = sy;
return result;
}
}
: public int[] solution(String[] park, String[] routes) { park랑 routes 입력받기
char arr[][] = new char[park.length][park[0].length()]; [행개수][열개수]
int result[] =new int[2]; 출력 배열
int sx = 0; 시작행 초기화
int sy = 0; 시작열 초기화
for(int i=0;i<park.length; i++){
arr[i]=park[i].toCharArray(); i행마다 park 한묶음씩 집어넣고 j열에 묶음 쪼개기
for(int j=0; j<park[0].length();j++){ 한묶음 안의 원소개수 만큼 열 만들기
if(arr[i][j]=='S'){ S라고 하면 시작지점
sx=i; 행
sy=j; 열
}
}
}
for(String route : routes){ 입력받은 routes 배열 한묶음씩 보기
String dir = route.split(" ")[0]; 0번째가 방향
int move = Integer.parseInt(route.split(" ")[1]); 1번째가 움직일 칸 개수
int nx = sx; 시작지점으로 nx 초기화
int ny = sy; 시작지점으로 ny 초기화
for(int j=0; j<move; j++){ routes의 한묶음 안의 원소 다 살펴보기
switch(dir){ 방향이 무엇인지 보고 그에 맞는 명령어 대입
case "E": ny++; break; 열 이동 (보이는건 가로 변화)
case "W": ny--; break; 열 이동 (보이는건 가로 변화)
case "N": nx--; break; 행 이동 (보이는건 세로 변화)
case "S": nx++; break; 행 이동 (보이는건 세로 변화)
}
if (nx < 0 || ny >= park[0].length() || ny < 0 || nx >= park.length || arr[nx][ny] == 'X') {
nx = sx; 이동이 불가할 경우 현지점을 다시 시작지점으로 되돌린다
ny = sy; switch 연산 이전으로 되돌리기
break; 더 갈 것도 없이 바로 중단
}
if (j == move - 1) { for문 마지막 순간에 뽑아내기
sx = nx; 시작지점을 지금의 지점으로 갱신
sy = ny; 시작지점을 지금의 지점으로 갱신
}
}
}
result[0] = sx; 도착 행 저장
result[1] = sy; 도착 열 저장
return result; 결과 출력
}
}
https://school.programmers.co.kr/learn/courses/30/lessons/172928?language=java
프로그래머스
코드 중심의 개발자 채용. 스택 기반의 포지션 매칭. 프로그래머스의 개발자 맞춤형 프로필을 등록하고, 나와 기술 궁합이 잘 맞는 기업들을 매칭 받으세요.
programmers.co.kr
'Programmers > Lv.1' 카테고리의 다른 글
[프로그래머스] Lv.1 바탕화면 정리 JAVA 풀이 (0) | 2024.06.28 |
---|---|
[프로그래머스] Lv.1 크레인 인형뽑기 JAVA 풀이 (0) | 2023.10.02 |
[프로그래머스] Lv.1 덧칠하기 JAVA 풀이 (0) | 2023.08.24 |
[프로그래머스] Lv.1 추억 점수 JAVA 풀이 (2) | 2023.08.21 |
[프로그래머스] Lv.1 달리기 경주 JAVA 풀이 (0) | 2023.08.21 |