https://school.programmers.co.kr/learn/courses/30/lessons/172928
더보기 주의 , 코드에 관한 설명이 간략히 있지만 코드 내용 원문이 있으니 주의 할 것
<나의 풀이 (비추천)>
park의 위치를 문자열로 준것을 보고 2차원 배열을 이용하자 생각했고
routes의 문자열로 방향과 이동거리를 주는것을보고 문자열을 쪼갤때 많이 쓰는 <sstream>헤더를 활용하자 생각을 하였다.
또한 각 방향에 따라 수치들이 변경되는게 많아 define을 사용하여 매크로 상수화 했다.
(enum 쓰는게 가독성이 올라가는데 문제라서 그냥 define으로 하였다.)
이동 할떄 사용한 정보(경로)를 기록할 필요가 없어 전부 for 반복문 안에 지역변수로 활용하였다.
이 문제의 제일 중요한 것은 '강아지 이동'을 시킬때 조건 2가지가 중요하다
조건 1. 경계선이 벗어나면 다음 명령을 실행하고, 경계선 안에 있으면
조건 2. 이동 범위 안에 장애물이 있는지 확인을 하고 장애물이 있으면 다음 명령을 실행하게 해놨다.
조건1,조건2를 전부 만족할경우 현재 강아지의 좌표를 변경해주는 식으로 진행하였다.
간략한 내용은 플로우차트에 적어놨다.
플로우 차트 밑에 기능적으로 함수화를 하면 가독성이 많이 올라간다.
<플로우 차트>
0. 사전 준비
0-1. Park 지도를 만들기 (2차원 배열화)
0-1-1. Park 지도를 만들면서 (시작지점과 , 장애물지점을 설치)
(// 0:길 1:장애물 2:로봇강아지 )
1.routes 리스트의 data를 사용할수 있는 형식으로 만들기
1-1.방향(E,W,N,S) 와 이동거리(Move) 형식으로 만들기
2.강아지 진행시키기
(조건 1: 최종 위치기 경계선을 벗어나면 , 명령 동작x)
(조건 2: 이동경로에 장애물이 있는경우, 명령 동작x)
#include <string>
#include <vector>
#include <sstream>
#define UP_OR_LEFT -1
#define DOWN_OR_RIGHT 1
#define MOVE_X 1
#define MOVE_Y -1
#define PARK_ROAD 0
#define PARK_OBJECT 1
#define PARK_DOG 2
using namespace std;
vector<int> solution(vector<string> park, vector<string> routes)
{
vector<int> answer;
int width = park[0].length();
int height = park.size();
int dog_x =0, dog_y =0; // 로봇강아지 현재좌표
//0-1. Park 지도를 만들기 (2차원 배열화)
vector<vector<int>> Park_map(height,vector<int>(width,0));
//0-1-1. Park 지도를 만들면서 (시작지점과 , 장애물지점을 설치)
// (0:길 1:장애물 2:로봇강아지 )
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
//시작 지점 기록
if (park[y][x] == 'S')
{
dog_x = x;
dog_y = y;
Park_map[y][x] = 2;
}
//장애물 위치 기록
else if (park[y][x] == 'X')
{
Park_map[y][x] = 1;
}
}
}
int routes_roop = routes.size();
for (int route_index = 0; route_index < routes_roop; route_index++)
{
//1.routes 리스트의 data를 사용할수 있는 형식으로 만들기
// 1 - 1.방향(E, W, N, S) 와 이동거리(Move) 형식으로 만들기
char dir;
int move = 0;
stringstream stream;
stream.str(routes[route_index]);
stream >> dir;
stream >> move;
//------------------------------------------------------------
/* 2.강아지 진행시키기
(조건 1: 최종 위치기 경계선을 벗어나면 , 명령 동작x)
(조건 2: 이동경로에 장애물이 있는경우, 명령 동작x) */
int dir_add = 0; // 방향 이동시 -,+ 결정
int move_axis = 0; // 이동하는 축 결정
bool move_check = true;
switch (dir)
{
case 'E' :
dir_add = DOWN_OR_RIGHT;
move_axis = MOVE_X;
break;
case 'W':
dir_add = UP_OR_LEFT;
move_axis = MOVE_X;
break;
case 'S':
dir_add = DOWN_OR_RIGHT;
move_axis = MOVE_Y;
break;
case 'N':
dir_add = UP_OR_LEFT;
move_axis = MOVE_Y;
break;
}
int move_result = move * dir_add; //이동거리 * 방향결정 = 강아지가 움질익 방향
int move_min, move_max,move_tmp; // 이동 범위
switch (move_axis)
{
case MOVE_X:
//(조건 1: 최종 위치기 경계선을 벗어나면 , 명령 동작x)
if (dog_x + move_result >= width || dog_x + move_result < 0)
{
break;
}
//이동 범위 계산
move_min = dog_x;
move_max = dog_x + move_result;
if (move_min > move_max)
{
move_tmp = move_min;
move_min = move_max;
move_max = move_tmp;
}
//(조건 2: 이동경로에 장애물이 있는경우, 명령 동작x
for (int i = 0; i < move_max - move_min; i++)
{
int move_x = dog_x + (dir_add * (i + 1));
if (Park_map[dog_y][move_x] == PARK_OBJECT)
{
move_check = false;
break;
}
}
if (move_check)
{
Park_map[dog_y][dog_x] = PARK_ROAD;
dog_x += move_result;
Park_map[dog_y][dog_x] = PARK_DOG;
}
break;
case MOVE_Y:
//(조건 1: 최종 위치기 경계선을 벗어나면 , 명령 동작x)
if (dog_y + move_result >= height || dog_y + move_result < 0)
{
break;
}
//이동 범위 계산
move_min = dog_y;
move_max = dog_y + move_result;
if (move_min > move_max)
{
move_tmp = move_min;
move_min = move_max;
move_max = move_tmp;
}
//(조건 2: 이동경로에 장애물이 있는경우, 명령 동작x
for (int i = 0; i < move_max - move_min; i++)
{
int move_y = dog_y + (dir_add * (i + 1));
if (Park_map[move_y][dog_x] == PARK_OBJECT)
{
move_check = false;
break;
}
}
if (move_check)
{
Park_map[dog_y][dog_x] = PARK_ROAD;
dog_y += move_result;
Park_map[dog_y][dog_x] = PARK_DOG;
}
break;
}
}
answer.push_back(dog_y);
answer.push_back(dog_x);
return answer;
}
<다른사람의 풀이>
다른분이 풀은것을 보니 2차원 배열화를 할 필요가 없었다.
장애물때문에 2차원 배열하는게 좋을줄알았는데 그냥 park의 문자열 찾기로 x만 제외했으면 됬다.
또한 나같은경우는 매번 roop를 돌때마다 switch문을 들어가서 각 해당되는값을 정의했는데
들어가기전 필요한 data들을 세팅하고 반복문을 돌리는 형식이다.
<플로우 차트>
0. 사전 준비
0-1.dx,dy,mapping으로 각 방향시 이동하는 칸수 및 단일문자에 따른 인덱스값 설정
0-2. 시작 위치 좌표 알기 ( Park 반복문)
1. 강아지 이동경로 갯수만큼 roop
1-1. 강아지의 이동칸수 만큼 roop
1-1-1.강아지가 한칸 씩 이동하면서 장애물 체크 및 경계선 체크를 동시에 한다.
2.반복문이 roop를 다 돌은경우 현재 좌표 갱신
#include <string>
#include <vector>
#include <map>
using namespace std;
using pi = pair<int, int>;
//0 = S, 1 = N , 2 = E , 3 = W
int dx[4] = { 1, -1, 0, 0 };
int dy[4] = { 0, 0, 1, -1 };
map<char, int> mapping = {
{'E', 0}, {'W', 1}, {'S', 2}, {'N', 3}
};
vector<int> solution(vector<string> park, vector<string> routes)
{
int cx, cy;
//시작 위치 좌표 알기
for (int i = 0; i < park.size(); ++i) {
for (int j = 0; j < park[i].size(); ++j) {
if (park[i][j] == 'S')
{
//tie : pair,tuple으로 구성 되어있을때, 여러개읜 return값이 필요할때 사용하는 명령어
tie(cx, cy) = { i, j };
break;
}
}
}
//강아지 경로 갯수만큼 반복문 roop
for (int i = 0; i < routes.size(); ++i) {
int num = routes[i][2] - '0'; // 이동거리 확인 , 문자열의 2번재 인덱스(숫자) ,char 자료형이기떄문에 아스키코드(0,-48)을 해서 int로 변경
int dir = mapping[routes[i][0]];//이동방향 단일문자 확인 , map에 키값을 넣고 int 값을 받아옴
int nx = cx, ny = cy;
while (num--) {
nx += dx[dir];
ny += dy[dir];
if (!(nx >= 0 && nx < park.size()) || !(ny >= 0 && ny < park[0].size())) break; // 경계선 체크
if (park[nx][ny] == 'X') break; // 장애물 체크
}
//해당 i의 이동roop를 다 돌은경우 좌표 갱신
if (num < 0) {
cx = nx;
cy = ny;
}
}
return { cy, cx };
}
'코딩테스트 > 프로그래머스' 카테고리의 다른 글
LV.2 최솟값 만들기 (0) | 2023.06.09 |
---|---|
LV.1 내적 (0) | 2023.06.09 |
LV.1 없는 숫자 더하기 (0) | 2023.06.09 |
[LV2] 귤 고르기 (0) | 2023.05.31 |
[LV1] 대충 만든 자판 (0) | 2023.05.28 |