문제
가로 N칸, 세로 M칸으로 이루어진 격자판이 주어지고, 그 중 한 개의 칸에 로봇이 존재한다. 로봇은 동(E), 서(W), 남(S), 북(N) 4 방향으로 움직일 수 있다. 각 칸에는 로봇이 얻을 수 있는 점수가 적혀있거나 장애물이 존재한다. 점수는 자연수로 주어지며, 장애물은 -1로 주어진다. 로봇은 움직일 때 마다 자신이 위치해 있는 곳의 점수를 얻게 되고, 해당 칸의 값은 0으로 바뀌게 된다. 로봇의 초기 위치에는 장애물이 존재하지 않으며, 항상 초기 위치에 있는 점수를 얻으며 움직이기 시작한다.
성우는 총 L회 로봇을 움직일 수 있으며, 각 회마다 성우는 로봇이 이동할 방향과 크기를 정해줄 수 있다. 예를 들어, 한 회에 로봇을 서쪽으로 3칸 움직일 수 있다. 이렇게 로봇이 이동하는 동안 방문하는 칸에 있는 점수를 얻게 된다. 단, 이동 중에 장애물을 만나거나 격자판의 모서리에 닿게 되면 로봇이 그 즉시 이동을 멈추고 다음 명령을 수행한다.
이동 중 장애물을 만나거나 모서리 혹은 벽면에 닿은 경우 - 빨간 화살표
로봇을 움직이는 명령이 너무 단조롭다고 느낀 성우는, 로봇이 이동하는 크기를 조금 더 복잡하게 정해보고자 한다.
로봇이 움직이는 크기는 회전판을 돌림으로써 정해진다. 회전판은 K개의 칸으로 이루어져 있으며, 각 칸에는 자연수가 적혀있다. 성우는 각 회마다 판을 한 번 회전시키고, 회전 결과 한 개의 숫자가 선택된다. 이 숫자만큼 로봇이 이동하게 된다. 그리고 회전판은 최초인 경우에는 지정된 기준에 따르고, 여러번 돌린 경우에는 직전 회전 결과를 기준으로 회전판을 돌린다.
성우는 판을 시계방향 혹은 반시계방향으로 판을 회전시킬 수 있다. 또한, 성우는 힘조절을 완벽하게 하기 때문에 판을 회전시킬 때에는 정확히 특정 칸 수만큼만 회전시킬 수 있다. 예를 들어, 크기 5인 회전판이 있고, 이는 위의 그림과 같다고 하자. 이 상황에서 성우가 회전판을 시계방향으로 회전시키면서 정확히 7칸만큼만 움직였다고 하자. 그러면 화살표는 0 → 1 → 3 → 5 → 2 → 0 → 1 순서대로 숫자를 가리키므로, 회전판은 마지막으로 숫자 1을 가리킨다. 따라서 로봇이 이동하는 크기는 1이 된다.
성우는 회전판과 함께 최종적으로 다음과 같은 명령을 내린다. 이 명령은 (이동 방향, 회전 방향, 회전시키는 칸 수) 로 주어진다. 회전 방향의 경우, 1은 시계방향을 나타내고 2는 반시계방향을 나타낸다. 다음은 이 명령의 예를 나타낸다.
N 1 2 : 회전판을 시계 방향으로 회전하며 2칸만큼 움직이고, 가리키는 숫자만큼 로봇을 북쪽으로 이동시킨다.
E 2 8 : 회전판을 시계 반대방향으로 회전하며 8칸만큼 움직이고, 가리키는 숫자만큼 로봇을 동쪽으로 이동시킨다.
예를 들어, 지도와 회전판의 초기 상태가 위의 그림과 같고, 로봇이 (2, 5)에 위치해있는 경우에 “N 1 3” 의 명령을 내렸다고 하자. 그러면 성우는 시계방향으로 판을 회전시키면서 정확히 3칸을 움직이게 되므로, 회전판은 0 → 1 → 3 의 순서대로 숫자를 가리키게 된다. 따라서 북쪽으로 3만큼 움직이므로, 로봇의 최종 위치는 (2, 2)가 된다.
성우가 로봇을 L회 움직일 때, 로봇이 얻는 총 점수와 로봇의 최종위치 (x’, y’)를 출력하는 프로그램을 작성하시오.
입력
첫째 줄에는 테스트 케이스 T (1 <= T <= 10)가 주어지고, 그 다음 줄에 도로의 가로의 크기 N과 세로의 크기 M, 그리고 로봇의 현재 위치 X, Y 가 빈칸을 사이에 두고 주어진다. (1 <= N, M, X, Y <= 500) 다음 M개의 줄에 대하여 판의 상태가 주어진다. 각 칸에는 점수 혹은 장애물이 있으며, 점수는 200이하의 자연수로 주어지고 장애물은 -1로 주어진다.
그 후 다음 줄에 회전판에 존재하는 칸의 개수 K(1 <= K <= 8) 가 주어지고, 다음 줄에 회전판의 값들이 K개의 1000이하 자연수로 주어진다. 숫자는 회전판의 시계방향으로 주어지며, 회전판은 초기에 가장 앞의 숫자를 가리키고 있다.
그 다음 줄에 성우가 로봇을 움직이는 횟수 L(1 <= L <= 500) 이 주어지고, 이어 L개의 줄에 걸쳐 로봇을 움직이는 명령이 주어진다. 각 명령은 이동할 방향, 회전 방향, 회전시키는 칸 수로 이루어져 있다. 회전 방향의 경우, 시계 방향은 1로 주어지며 반시계방향은 2로 주어진다. 회전시키는 칸 수의 경우 100 이하의 자연수이다.
출력
T개의 테스트 케이스 각각에 대하여 로봇의 최종 위치와 점수를 출력한다. 각 줄은 “#x”, 로봇이 얻은 점수, 그리고 로봇의 최종 위치(x’, y’)를 각각 공백을 두고 출력한다. 단, x는 1부터 시작하는 테스트 케이스의 번호를 나타낸다.
예제 입력 (stdin)
2
5 6 1 2
0 1 1 2 3
2 5 -1 2 0
10 29 17 -1 3
5 4 7 9 12
11 19 -1 12 4
7 8 9 1 3
3
2 4 1
3
S 1 2
N 2 1
E 2 5
5 6 2 5
0 1 1 2 3
2 5 -1 2 0
10 29 17 -1 3
5 4 7 9 12
11 19 -1 12 4
7 8 9 1 3
5
2 5 3 1 0
5
S 1 3
N 1 4
W 2 1
N 1 7
E 1 1
예제 출력 (stdout)
#1 54 2 5
#2 65 2 2
예제 설명
로봇은 (1, 2) 에서부터 출발하여 그림과 같이 움직인다. 따라서 얻게 되는 점수는 54이며, 마지막 로봇의 위치는 (2, 5)이다.
#내코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
testCase = int(input())
for tt in range(testCase):
getInfo = list(map(int, input().split()))
row = getInfo[1]
col = getInfo[0]
#현재위치
xPos = getInfo[2]
yPos = getInfo[3]
resultValue = 0
getFrame = [list(map(int, input().split())) for _ in range(row)]
frame = [[-1 for _ in range(col+2)] for _ in range(row+2)]
for i in range(len(getFrame)):
for j in range(len(getFrame[i])):
frame[i+1][j+1] = getFrame[i][j]
resultValue = frame[yPos][xPos]
frame[yPos][xPos] = 0 # 초기화 중요!!
circleCnt = int(input())
circle = list(map(int, input().split()))
moveCnt = int(input())
moveInfo = list()
for i in range(moveCnt):
moveInfo.append(list(input().split()))
# W(좌) : 0, E(우) : 1, S(하) : 2, N(상) : 3
x = [-1, 1, 0, 0]
y = [0, 0, 1, -1]
idx = 0
for i in range(len(moveInfo)):
d = moveInfo[i][0]
dNum = 0
if d == 'W': dNum = 0
elif d == 'E': dNum = 1
elif d == 'S': dNum = 2
elif d == 'N': dNum = 3
direction = int(moveInfo[i][1]) #이동 방향 1: 시계 2: 반시계
m_cnt = int(moveInfo[i][2]) #이동 칸 수
# 회전판을 돌린다
# 1. 정방향 : 2 -> 1 -> 4(testcase_1)
if direction == 1:
for _ in range(m_cnt):
if idx <= 0: idx = len(circle)-1
else: idx -= 1
# 2. 역방향 : 2 -> 4 -> 1(testcase_1)
if direction == 2:
for _ in range(m_cnt):
if idx >= len(circle)-1: idx = 0
else: idx += 1
# 실제 칸을 이동시킨다.
for mm in range(circle[idx]):
if frame[yPos+y[dNum]][xPos+x[dNum]] == -1: break
yPos += y[dNum]
xPos += x[dNum]
resultValue += frame[yPos][xPos]
frame[yPos][xPos] = 0
print('#'+str(tt+1), resultValue, xPos, yPos)
|
cs |
'CS > 알고리즘_문제풀이(파이썬)' 카테고리의 다른 글
division(백트래킹) (0) | 2021.05.17 |
---|---|
순열구하기(백트래킹) (0) | 2021.05.17 |
baseball game (0) | 2021.05.16 |
이동 알고리즘 (0) | 2021.05.15 |
경계 처리 알고리즘 (0) | 2021.05.15 |