백준 삼성 코딩 기출 문제 - 구슬 탈출 python
출처 : BAEKJOON ONLINE JUDGE
구슬 탈출(https://www.acmicpc.net/problem/13459)
문제 설명
보드가 N X M 크기로 있고, 중력을 통해서 떨어지기 때문에 기울이는 것을 통해서 위/아래/오른쪽/왼쪽으로 움직임이 가능합니다. 빨간 구슬(R)을 구멍(O)으로 움직여야 하고, 단 파란 구슬(B)가 구멍(O)으로 들어가거나 또는 같이 들어가도 실패합니다. 움직이는 횟수는 총 10번 이하로 제한되고 가능하면 1, 실패하면 0을 출력합니다.
문제 풀이
BFS(Breadth-First-Search) 알고리즘은 queue(FIFO -> deque사용)과 while(무한 루프)를 사용해 탐색을 구현합니다. DFS(Depth First Search) 알고리즘은 stack(LIFO)과 재귀 함수 사용해 구현해야 합니다.
여기서는 BFS 알고리즘을 통해서 탐색을 진행합니다.
[1] 전체 행렬의 row에 해당하는 n, column의 크기는 m 그리고 보드인 board 입력을 받습니다.
- from sys import stdin을 이용해서 입력을 받습니다.
- board를 출력하면 다음과 같은 형태로 저장됩니다.
[2] 빨간 구슬, 파란 구슬 2개가 동시에 움직이므로, 각 2개의 구슬 x, y좌표를 visited 배열에 4차원으로 선언하고 False로 초기화합니다. 그리고 while문을 통해 bfs 탐색을 진행하면서 방문 여부를 확인하고 방문을 안했다면 queue에 넣고, True로 체크하게 됩니다.
[3] 구슬이 움직일 수 있는 x, y의 좌표를 만들고, collection의 deque를 이용해 queue를 생성합니다.
[4] 보드에서 빨간 구슬(R)과 파란 구슬(B)가 어느 x, y 좌표에 있는지가 중요합니다.
- 문자열 비교를 통해 x, y 위치를 가져오고, queue에 넣을 때는 현재 몇 번 구슬을 움직 였는 지에 대한 정보를 저장하는 depth를 저장합니다. depth는 1로 초기화합니다.
- 따라서 큐에는 (빨간 구슬 x, y, 파란 구슬 x, y, 몇 번 구슬 움직였는지 )가 들어가게 되죠. 또한 visited 배열에 해당 구슬 정보를 True로 넣고 값을 업데이트합니다.
[5] 다음은 구슬이 움직임이 가능하기 때문에 move라는 함수로 구현을 합니다.
- 벽(#) 또는 구멍(O)이 아닐 때 까지 정해진 방향으로 전진합니다.
- 여기서 이동한 칸 수를 저장하는 count라는 변수가 있습니다. 이 변수는 depth와는 전혀 상관이 없고, 빨간 구슬과 파란 구슬이 겹쳐서는 안된다라는 조건을 풀기 위해 쓰이는 변수입니다.
- 같은 방향으로 움직이는 가운데 2개의 구슬이 겹친다는 조건이면 둘 중 하나의 구슬의 움직이는 칸 수를 하나 줄여야 됩니다. 따라서 같이 움직이지만 서로 겹치지 않겠죠. 움직임이 가장 많은 구슬이 한 칸 적어야할 것입니다. 이를 판단하기 위해 count에 움직인 칸 수를 저장합니다.
[6] 핵심인 bfs 탐색입니다.
- 큰 구조로는 초기화를 하고, queue에 값이 없을 때 까지 while문을 돌게 됩니다.
- while 문 안에서는 popleft()를 통해서 FIFO 구조에 따라 처음에 위치한 값을 가지고 옵니다.
- 10번 이하여야 한다는 조건을 먼저 봅니다. 넘어서면 break로 while문을 종료해버립니다.
- 다음으로는 4방향으로 움직일 수 있는지 시도를 해야 합니다. move를 써서 이동합니다.
- 이동한 x, y좌표 값을 토대로 판단을 진행합니다. 파란 구슬(B)이 구멍(O)에 떨어졌다면 실패이므로 continue문으로 넘어갑니다.
- 위의 조건을 지나면, 파란 구슬이 안떨어진 경우이며, 빨간 구슬(R)이 구멍(O)에 떨어졌다면 성공이므로 print(1)을 하고 return 문으로 반복문을 종료 함수의 결과값을 리턴합니다.
- 만약에 빨간 구슬과 파란 구슬이 겹쳐진다면, count(구슬이 움직인 칸 수)를 기반으로 많이 움직인 구슬을 현재 방향 기준으로 뒤로 한칸 물립니다.
- 마지막은 방문 여부를 확인합니다. 방문하지 않았다면 visited 배열에서 True로 체크하고 queue에 넣습니다.
- 10번을 넘어 버리면 실패이므로 print(0)을 출력하고 마칩니다.
첫 번째 테스트 케이스를 보죠.
보는 입장에서는 빨간 구실이 오른쪽으로 한 칸으로 이동하면 성공입니다.
배열로 구성된 보드를 움직이려면 row 인덱스에 해당하는 0이고, column 인덱스에 해당하는 1이면 오른쪽으로 움직입니다. x, y 좌표계에 따라서 x로 +1이동하면 되는거 아닌가.. 헷갈립니다. 그런 경우를 방지하고자 row와 column 인덱스를 생각해보세요.
- row 인덱스는 0번째 인덱스로 시작해 +1이면 아래로, -1이면 위로 움직입니다.
- column 인덱스는 0번째 인덱스로 시작해 오른쪽으로는 +1 왼쪽으로는 -1을 해야 움직입니다.
2번째 케이스도 비슷합니다.
전체 코드
'Algorithm' 카테고리의 다른 글
백준 삼성 코딩 기출 문제 - 2048 (Easy) python (4) | 2019.10.16 |
---|---|
백준 삼성 코딩 기출 문제 - 구슬 탈출2 python (0) | 2019.10.16 |
python 부분합, 연속 부분수열 최대합 (0) | 2019.09.27 |
Python 구간 사이의 최소 제곱근 찾기 (0) | 2019.09.27 |
graph shortest path - 최단 경로 다익스트라 알고리즘 python (0) | 2019.09.27 |
백준 삼성 코딩 기출 문제 - 구슬 탈출 python
출처 : BAEKJOON ONLINE JUDGE
구슬 탈출(https://www.acmicpc.net/problem/13459)
문제 설명
보드가 N X M 크기로 있고, 중력을 통해서 떨어지기 때문에 기울이는 것을 통해서 위/아래/오른쪽/왼쪽으로 움직임이 가능합니다. 빨간 구슬(R)을 구멍(O)으로 움직여야 하고, 단 파란 구슬(B)가 구멍(O)으로 들어가거나 또는 같이 들어가도 실패합니다. 움직이는 횟수는 총 10번 이하로 제한되고 가능하면 1, 실패하면 0을 출력합니다.
문제 풀이
BFS(Breadth-First-Search) 알고리즘은 queue(FIFO -> deque사용)과 while(무한 루프)를 사용해 탐색을 구현합니다. DFS(Depth First Search) 알고리즘은 stack(LIFO)과 재귀 함수 사용해 구현해야 합니다.
여기서는 BFS 알고리즘을 통해서 탐색을 진행합니다.
[1] 전체 행렬의 row에 해당하는 n, column의 크기는 m 그리고 보드인 board 입력을 받습니다.
- from sys import stdin을 이용해서 입력을 받습니다.
- board를 출력하면 다음과 같은 형태로 저장됩니다.
[2] 빨간 구슬, 파란 구슬 2개가 동시에 움직이므로, 각 2개의 구슬 x, y좌표를 visited 배열에 4차원으로 선언하고 False로 초기화합니다. 그리고 while문을 통해 bfs 탐색을 진행하면서 방문 여부를 확인하고 방문을 안했다면 queue에 넣고, True로 체크하게 됩니다.
[3] 구슬이 움직일 수 있는 x, y의 좌표를 만들고, collection의 deque를 이용해 queue를 생성합니다.
[4] 보드에서 빨간 구슬(R)과 파란 구슬(B)가 어느 x, y 좌표에 있는지가 중요합니다.
- 문자열 비교를 통해 x, y 위치를 가져오고, queue에 넣을 때는 현재 몇 번 구슬을 움직 였는 지에 대한 정보를 저장하는 depth를 저장합니다. depth는 1로 초기화합니다.
- 따라서 큐에는 (빨간 구슬 x, y, 파란 구슬 x, y, 몇 번 구슬 움직였는지 )가 들어가게 되죠. 또한 visited 배열에 해당 구슬 정보를 True로 넣고 값을 업데이트합니다.
[5] 다음은 구슬이 움직임이 가능하기 때문에 move라는 함수로 구현을 합니다.
- 벽(#) 또는 구멍(O)이 아닐 때 까지 정해진 방향으로 전진합니다.
- 여기서 이동한 칸 수를 저장하는 count라는 변수가 있습니다. 이 변수는 depth와는 전혀 상관이 없고, 빨간 구슬과 파란 구슬이 겹쳐서는 안된다라는 조건을 풀기 위해 쓰이는 변수입니다.
- 같은 방향으로 움직이는 가운데 2개의 구슬이 겹친다는 조건이면 둘 중 하나의 구슬의 움직이는 칸 수를 하나 줄여야 됩니다. 따라서 같이 움직이지만 서로 겹치지 않겠죠. 움직임이 가장 많은 구슬이 한 칸 적어야할 것입니다. 이를 판단하기 위해 count에 움직인 칸 수를 저장합니다.
[6] 핵심인 bfs 탐색입니다.
- 큰 구조로는 초기화를 하고, queue에 값이 없을 때 까지 while문을 돌게 됩니다.
- while 문 안에서는 popleft()를 통해서 FIFO 구조에 따라 처음에 위치한 값을 가지고 옵니다.
- 10번 이하여야 한다는 조건을 먼저 봅니다. 넘어서면 break로 while문을 종료해버립니다.
- 다음으로는 4방향으로 움직일 수 있는지 시도를 해야 합니다. move를 써서 이동합니다.
- 이동한 x, y좌표 값을 토대로 판단을 진행합니다. 파란 구슬(B)이 구멍(O)에 떨어졌다면 실패이므로 continue문으로 넘어갑니다.
- 위의 조건을 지나면, 파란 구슬이 안떨어진 경우이며, 빨간 구슬(R)이 구멍(O)에 떨어졌다면 성공이므로 print(1)을 하고 return 문으로 반복문을 종료 함수의 결과값을 리턴합니다.
- 만약에 빨간 구슬과 파란 구슬이 겹쳐진다면, count(구슬이 움직인 칸 수)를 기반으로 많이 움직인 구슬을 현재 방향 기준으로 뒤로 한칸 물립니다.
- 마지막은 방문 여부를 확인합니다. 방문하지 않았다면 visited 배열에서 True로 체크하고 queue에 넣습니다.
- 10번을 넘어 버리면 실패이므로 print(0)을 출력하고 마칩니다.
첫 번째 테스트 케이스를 보죠.
보는 입장에서는 빨간 구실이 오른쪽으로 한 칸으로 이동하면 성공입니다.
배열로 구성된 보드를 움직이려면 row 인덱스에 해당하는 0이고, column 인덱스에 해당하는 1이면 오른쪽으로 움직입니다. x, y 좌표계에 따라서 x로 +1이동하면 되는거 아닌가.. 헷갈립니다. 그런 경우를 방지하고자 row와 column 인덱스를 생각해보세요.
- row 인덱스는 0번째 인덱스로 시작해 +1이면 아래로, -1이면 위로 움직입니다.
- column 인덱스는 0번째 인덱스로 시작해 오른쪽으로는 +1 왼쪽으로는 -1을 해야 움직입니다.
2번째 케이스도 비슷합니다.
전체 코드
'Algorithm' 카테고리의 다른 글
백준 삼성 코딩 기출 문제 - 2048 (Easy) python (4) | 2019.10.16 |
---|---|
백준 삼성 코딩 기출 문제 - 구슬 탈출2 python (0) | 2019.10.16 |
python 부분합, 연속 부분수열 최대합 (0) | 2019.09.27 |
Python 구간 사이의 최소 제곱근 찾기 (0) | 2019.09.27 |
graph shortest path - 최단 경로 다익스트라 알고리즘 python (0) | 2019.09.27 |