*문제 출처는 코드트리에 있습니다.
문제 제목: 왕실의 기사 대결
문제 사이트: https://www.codetree.ai/problems/royal-knight-duel/description
나의 풀이 - 해결!
주의할 점:
먼저, 기사가 이동할때 이동된 기사는 피해를 입지않고
밀려나간 기사는 해당 밀려나간 위치에 함정이 있으면 체력이 깎인다.
밀려나가서 함정에 걸려 체력이 깎인 기사는 체력이 0이되면 없는것과 마찬가지이다.
연쇄적으로 밀려나갈때, 벽(2) 이나 좌표를 벗어나면 벽에 해당되므로 해당 구간에서는 기사를 밀 수 없어 다른 명령으로 넘어가야한다.
(해당 명령은 진행될 수 없음)
밀려나갈 기사가 없으면 그냥 혼자 이동하면 된다. 대신 명령을 받은 기사는 체력이 깎이지 않는다. 하지만 벽이 있으면 이동하지 못하는 것은 마찬가지
그래서 생존한 기사들의 데미지 차를 구하면 된다.(죽은 기사 제외임)
이전코드에서 아주 간단한 조건절 하나를 빠트려서 틀렸었다.
바로 이코드임...
# 연쇄적으로 기사가 밀리는지 확인
def BFS(quest, d):
# 해당 기사가 죽어도 명령을 받긴 한다 하지만 반응 없음
# quest 기사 d로 가라
if solders[quest][1] == 0:
# 이걸 설정 안해주면 명령 받고
# 죽은 기사는 안움직여도 해당 부분이 빈칸이라서 다른 기사들이 움직이므로
return []
이전에는 죽은 기사가 명령을 받아도 어차피 죽었으니 해당칸 상관 없다 싶었는데,
그냥 명령을 받아도 '무반응'으로 해서 넘겨야 테스트케이스가 통과된다.
최종 코드
from collections import deque
L, N, Q = map(int, input().split())
# L x L 체스판
maps = [list(map(int, input().split())) for _ in range(L)]
init_solders = {i+1: [] for i in range(N)}
solders = {i+1: [] for i in range(N)}
solder_map = [[0]*L for _ in range(L)]
# 초기 기사 정보 입력
for t in range(N):
r, c, h, w, k = map(int, input().split())
points = []
for i in range(r-1, r-1+h):
for j in range(c-1, c-1+w):
points.append([i, j])
solder_map[i][j] = t+1
solders[t+1].append(points)
solders[t+1].append(k)
init_solders[t+1].append(points)
init_solders[t+1].append(k)
# 왕의 명령 리스트
Quest_list = [list(map(int, input().split())) for _ in range(Q)]
# 연쇄적으로 기사가 밀리는지 확인
def BFS(quest, d):
# 해당 기사가 죽어도 명령을 받긴 한다 하지만 반응 없음
# quest 기사 d로 가라
if solders[quest][1] == 0:
# 이걸 설정 안해주면 명령 받고
# 죽은 기사는 안움직여도 해당 부분이 빈칸이라서 다른 기사들이 움직이므로
return []
queue = deque(solders[quest][0])
move_solder = set([quest])
visited = set(tuple(pos) for pos in solders[quest][0]) # 방문 위치 저장
while queue:
q = queue.popleft()
qx, qy = q[0], q[1]
x = qx + d[0]
y = qy + d[1]
if 0 <= x < L and 0 <= y < L and maps[x][y] != 2: # 벽이 아니면 진행
if solder_map[x][y] != 0 and solder_map[x][y] not in move_solder:
queue.extend(solders[solder_map[x][y]][0])
move_solder.add(solder_map[x][y])
visited.add((x, y))
else:
return [] # 벽에 막히면 이동 실패
return move_solder
# 각 명령에 대해 처리
for i in Quest_list:
d = ((-1, 0), (0, 1), (1, 0), (0, -1)) # 방향: 상, 우, 하, 좌
s_n = i[0] # 기사 번호
s_d = d[i[1]] # 이동 방향
move = BFS(s_n, s_d)
if move:
solder_map = [[0] * L for _ in range(L)] # 맵 초기화
for nums in move: # 이동할 기사들 처리
solders[nums][0] = [[x + s_d[0], y + s_d[1]] for x, y in solders[nums][0]]
# 기사들 이동 후 맵 업데이트
for sol_num in solders:
for x, y in solders[sol_num][0]:
if sol_num in move:
if maps[x][y] == 1: # 함정일 경우
if solders[sol_num][1] > 0 and sol_num != s_n:
solders[sol_num][1] -= 1 # 데미지 처리
if solders[sol_num][1] <= 0:
solder_map[x][y] = 0 # 기사 제거
else:
solder_map[x][y] = sol_num # 기사 유지
# 생존한 기사들의 피해 계산
damage = 0
for solder in solders:
if solders[solder][1] > 0:
damage += init_solders[solder][1] - solders[solder][1] # 체력 감소량 계산
print(damage)
이전코드
from collections import deque
L, N, Q = map(int,input().rstrip().split())
maps = [list(map(int,input().rstrip().split())) for _ in range(L)]
init_solders = {i+1: [] for i in range(N)}
solders = {i+1: [] for i in range(N)}
# 주어진 초기 좌표와 면적을 계산
# {1: [[[0, 1], [1, 1]], 5], 2: [[[1, 0], [2, 0]], 1], 3: [[[2, 1], [2, 2]], 3]}
solder_map = [[0]*L for _ in range(L)]
for t in range(N):
r, c, h, w, k = map(int, input().rstrip().split())
points = []
for i in range(r-1,r-1+h):
for j in range(c-1,c-1+w):
points.append([i,j])
solder_map[i][j] = t+1
solders[t+1].append(points)
solders[t+1].append(k)
init_solders[t+1].append(points)
init_solders[t+1].append(k)
Quest_list = [list(map(int,input().rstrip().split())) for _ in range(Q)]
def BFS(quest,d):
queue = deque(solders[quest][0])
move_solder = set([quest])
# 연쇄적이게 밀리는지 확인
while queue:
q = queue.popleft()
qx,qy = q[0],q[1]
x = qx + d[0]
y = qy + d[1]
if 0 <= x < L and 0 <= y < L and maps[x][y] != 2:
if solder_map[x][y] != 0 and solder_map[x][y] not in move_solder:
queue.extend(solders[solder_map[x][y]][0])
move_solder.add(solder_map[x][y])
else:
return []
return move_solder
for i in Quest_list:
d = ((-1,0),(0,1),(1,0),(0,-1))
s_n= i[0] # solder_num
s_d = d[i[1]] # solder_direction
move = BFS(s_n,s_d)
if move:
solder_map = [[0] * L for _ in range(L)]
for nums in move: # 밀려나는 기사들
solders[nums][0] = [[x+s_d[0], y+s_d[1]] for x,y in solders[nums][0]]
# 맵 업데이트
for sol_num in solders:
for x,y in solders[sol_num][0]:
if sol_num in move:
if maps[x][y] == 1:
# 명령 받은 기사는 피해 입지 않음
if solders[sol_num][1] > 0 and sol_num != s_n:
solders[sol_num][1] -= 1
if solders[sol_num][1] == 0:
solder_map[x][y] = 0
else:
solder_map[x][y] = sol_num
damage = 0
for solder in solders:
if solders[solder][1] > 0:
damage += init_solders[solder][1] - solders[solder][1]
print(damage)
※ 알아야 할 것
- 문제의 요지 숨겨진 조건 하나하나 다 파악하기!!!!
- 문제 풀기 전, 누가 봐도 sudo코드만 보고 문제를 다 파악할 수 있게끔 sudo코드 구현하기