728x90
싸움땅
- 링크:https://www.codetree.ai/training-field/frequent-problems/problems/battle-ground/description
- 기출: 삼성 SW 역량테스트 2022 하반기 오전 1번 문제
- 난이도:골드 1
- 분류: 시뮬레이션
- 직접 푼 여부: O (문제이해: 15m, 노트에 틀 짜기: 60m, 코드 짜기: 60m, 디버깅 20m ==> 2시간 35분)
- 언어: 파이썬
풀이 노트
이번 풀이의 순서는 (1) 문제 푸는 순서 , (2) 주의사항 - 내가 놓친 부분 , (3) 노트-문제이해, 코드 틀 이다. 정답코드는 젤 아래에 있으니 (+ 주석도 잘 달아놓음) 급하면 그것만 봐도 될 듯 하다.
1. 풀이 순서
(1) 문제 이해 - in/out
(2) 정의할 function 정하기 & 그 안에 중요한 사항
- [0] main 코드 틀
- [1] fight -싸움 처리
- [2] loose - fight 안에서 사용하는 함수로 진 선수를 처리
- [3] won - fight 안에서 사용하는 함수로 이긴 선수를 처리 - 지면, 총을 내려놓고, 그 총과 함께 비교해서 좋은 총을 이긴 사람이 선택하므로, won을 나중에 사용
- [4] gun_choos - 자신이 가진 총과 바닥에 있는 총 중에서 좋은 총 선택
(3) 사용할 변수들 생각
- 총의 위치 격자 3차원 list: gun_map : 총이 여러개 놓일 수 있으므로, 각 위치당 list를 사용함
- player 정보 list: player_list : player의 위치 (r,c), 방향(d), 스탯(s), 총의 스탯(g) 표시
- player의 map정보 2차원 list: player_map : 싸울지 말지를 정할 때 사용함
- point 정보 list: point_list
(4) 이후에는 아래와 같이 코드의 틀을 먼저 짜고 (완전 초기라 추가한 function은 사진내에 없다), 그 안을 채워넣으면 더 편하다. 그리고 각각의 파트에서 놓치면 안되는 것을 주석으로 써놓으면, 실수가 적어진다.
- 나는 보통 input, def, main문으로 나눠서 생각한다.
2. 주의사항 (내가 놓친 부분)
(1) "상 우 좌 하" 순인 것을 알고 있었지만, 잘못써서 틀렸다. 언제나 주의
(2) loose해서 움직일 때, direction을 업데이트 안 시켜줬다.
3. 노트
(1) 문제 이해 - in/out
(2) 정의할 function 정하기 & 그 안에 중요한 사항
정답 코드 💻
예제 맞추니 바로 통과해서 기분 좋다
# 싸움땅
import sys
input = sys.stdin.readline
# input ----------
def coverlist(x):
x=int(x)
if x!=0:
return [x]
else:
return []
n, m, k= map(int, input().split())
gun_map = [list(map(coverlist, input().split())) for _ in range(n)]
player_list = [[] for _ in range(m)] # [[r,c, d,s,g], ...]
player_map =[[[] for _ in range(n)] for _ in range(n)]
for i in range(m):
r,c,d,s = map(int,input().split())
player_list[i] = [r-1,c-1,d,s,0]
player_map[r-1][c-1].append(i)
# prepare ---------------------------
dr =[-1, 0, 1, 0] # 상 우 하 좌
dc = [0,1,0,-1]
rr, cc, dd, ss, gg = 0,1,2,3,4 # player 정보 바꾸기 편하게
point_list=[0]*m # 각자 point
# # def ----------------------------
def gun_choose(index):
"""
바닥에 있는 총과 내가 (index)가 가진 총 비교해서 선택
index: 사람 번호
"""
global gun_map, player_list
r,c,d,s,g = player_list[index]
if len(gun_map[r][c]) ==0: # 칸에 총이 없다면, 그냥 return
return
if g==0: # 총을 안가지고 있으면,
best_gun = max(gun_map[r][c])
player_list[index][gg] = best_gun
gun_map[r][c].remove(best_gun)
else: #총을 가지고 있다면,
best_gun = max(gun_map[r][c])
if g>=best_gun: # 내 총이 더 좋음
return
else:
gun_map[r][c].remove(best_gun)
gun_map[r][c].append(g) # 총 내려 놓고
player_list[index][gg] = best_gun # 총갖고
return
def won(index, point):
""""
이긴것 처리 (1) 총 max, (2) point 업데이트
"""
global gun_map, point_list
# 총
gun_choose(index)
# point
point_list[index] += point
return
def loose(index):
"""
진 것 처리 - (1) 총 내려 놓기, (2) 움직이기
index:진 player index
"""
global gun_map, player_list, player_map
# (1) 총 내려놓기 (총을 가지고 있을 때만)
r,c,d,s,g = player_list[index]
if g!=0:
player_list[index][gg] = 0
gun_map[r][c].append(g)
# (2) 이동
for i in range(4):
direction = (d+i)%4
newr, newc = r+dr[direction], c+dc[direction]
if not in_range(newr, newc) or len(player_map[newr][newc]) !=0:
# 못가는 곳이면, 90도 회전
continue
else:
# 갈 수 있으면, 이동
player_list[index][dd] = direction # 방향 update
player_list[index][rr], player_list[index][cc] = newr, newc
player_map[r][c].remove(index)
player_map[newr][newc].append(index)
# 총 줍기
if len(gun_map[newr][newc])!=0:
best_gun = max(gun_map[newr][newc])
player_list[index][gg] = best_gun
gun_map[newr][newc].remove(best_gun)
break
return
def fight(r,c):
"""
두사람 싸움
r,c: 현재 위치
"""
one, two = player_map[r][c]
oner, onec, oned, ones, oneg = player_list[one]
twor, twoc, twod, twos, twog = player_list[two]
point = abs((ones + oneg) - (twos + twog))
if ones+oneg > twos+twog:
# one이 이김
loose(two)
won(one,point)
elif ones+oneg < twos+twog:
# two가 이김
loose(one)
won(two, point)
else:
# 비김
if ones>twos: # one이 이김
loose(two)
won(one, point)
else:
loose(one)
won(two, point)
return
def in_range(newr, newc):
if 0<=newr<n and 0<=newc<n:
return True
else:
return False
# main ----------------------------
for _ in range(k): # k round
for i in range(m): # m 사람
r,c,d,s,g = player_list[i] # 위치, direction, 스탯, 총
newr, newc = r+dr[d], c + dc[d]
if not in_range(newr, newc): # 범위 나가면 , 반대방향으로
new_dir = (d+2)%4
newr, newc = r+dr[new_dir], c+dc[new_dir]
player_list[i][dd] = new_dir # 새로운 방향으로 update
# 위치 업데이트 - map & list
player_list[i][rr], player_list[i][cc] = newr, newc
player_map[r][c].remove(i)
player_map[newr][newc].append(i)
# 이동한 곳에 뭐가 있는지.
if len(player_map[newr][newc])!=1: # 사람이 있으면,
fight(newr, newc)
else: # 사람이 없으면 (len =1 이면 자기만 있는 것임)
gun_choose(i)
# 정답 출력
for i, point in enumerate(point_list):
if i<m-1:
print(point, end=" ")
else:
print(point)
728x90
'취준! ✒ > 삼성' 카테고리의 다른 글
[코테준비] 삼성20. 코드트리: 꼬리잡기놀이 python & 삼성식 출력 (0) | 2023.10.12 |
---|---|
[코테준비] 삼성19. 삼성 코테 준비전에 꼭 볼 것- SW Expert에 대해서! (feat. 보호 필름 문제 python) (1) | 2023.10.11 |
[코테준비] 삼성17. 코드트리: 코드트리 빵 python + 코드트리의 채점 무한로딩 (1) | 2023.10.09 |
[코테준비] 삼성16. 코드트리: 포탑 부수기 python (1) | 2023.10.07 |
[코테준비] 삼성15. 코드트리: 팩맨 python (1) | 2023.10.05 |