1. 문제 설명

ROR 게임은 두 팀으로 나누어서 진행하며, 상대 팀 진영을 먼저 파괴하면 이기는 게임이다. 따라서, 각 팀은 상대 팀 진영에 최대한 빨리 도착하는 것이 유리하다.

 

 

위 그림에서 검은색 부분은 벽으로 막혀있어 갈 수 없는 길이며, 흰색 부분은 갈 수 있는 길이다. 캐릭터는 동, 서, 남, 북으로 한 칸씩 이동하며, 게임 맵을 벗어난 길은 갈 수 없다.

 

 

첫번째 방법은 11칸을 지나서 도착이며, 두번째 방법은 15칸을 지나서 도착이다.

 

만약, 상대 팀이 자신의 티 진영 주변에 벽을 세워두었다면 상대 팀 진영에 도착하지 못할 수도 있다.

 

이때, 상대 팀 진영에 도착하기 위해 지나가야 하는 칸의 개수의 최솟값을 반환하여라.

 

 

 

2. 코드

(1) 1차 시도

dr = [1, 0, -1, 0] # row : 하 우 상 좌
dc = [0, 1, 0, -1] # column : 하 우 상 좌
minimum = 10001

def dfs(maps, now_r, now_c):
    global minimum
    n, m = len(maps), len(maps[0])

    if (now_r == n-1) and (now_c == m-1): # 적 진영에 도착한 경우
        if maps[now_r][now_c] < minimum:
            minimum = maps[now_r][now_c]
            return minimum

    for i in range(4):
        new_r = now_r + dr[i]
        new_c = now_c + dc[i]
        
        if new_r >= 0 and new_r <= (n-1) and new_c >= 0 and new_c <= (m-1):
            if maps[new_r][new_c] == 1:

                maps[new_r][new_c] = maps[now_r][now_c] + 1
                dfs(maps, new_r, new_c)
                maps[new_r][new_c] = 1
        
def solution(maps):
    global minimum
    now_r, now_c = 0, 0
    
    dfs(maps, now_r, now_c)
    
    if minimum == 10001:
        return -1
    
    return minimum

 

효율성 테스트를 통과하지 못했다.

 

 

(2) 2차 시도

from collections import deque

dr = [1, 0, -1, 0] # row : 하 우 상 좌
dc = [0, 1, 0, -1] # column : 하 우 상 좌

def bfs(maps, now_r, now_c):
    n, m = len(maps), len(maps[0])
    
    queue = deque()
    queue.append([now_r, now_c])
    
    while queue:
        r, c = queue.popleft()
        
        for i in range(4):
            new_r = r + dr[i]
            new_c = c + dc[i]

            if new_r >= 0 and new_r <= (n-1) and new_c >= 0 and new_c <= (m-1):
                if maps[new_r][new_c] == 0: 
                    continue

                if maps[new_r][new_c] == 1:
                    maps[new_r][new_c] = maps[r][c] + 1
                    queue.append([new_r, new_c])
                    
    return maps[n-1][m-1]
        
def solution(maps):
    r, c = 0, 0
    ans = bfs(maps, r, c)
    
    if ans == 1:
        return -1
    
    return ans

 

 

 

3. 설명

BFS로 문제를 풀면, 어떻게 하더라도 계속 시간 초과가 발생한다ㅠㅠ

그래서 아예 DFS로 바꿔서 풀었다.

 

- deque를 사용하여 현재 위치를 큐에 넣어두고, popleft()를 하여 현재 위치를 받아온다.

- 현재 위치 기준 상, 하, 좌, 우를 이동하면서 맵을 벗어나지 않고 1 값을 가지는 위치 모두를 큐에 저장한다. → 너비 우선 방식!

- 큐에 저장된 [행, 열] 좌표에 대해 maps 배열의 원소를 이전 좌표에 +1 한 값으로 바꿔주어, 해당 좌표까지 오는데 얼만큼의 비용이 들어가는지 저장한다.

 

- 만약 dfs()에서 반환한 값이 1인 경우는 적의 진영에 도달하지 못했다는 의미이므로 -1을 반환한다.

 

 

1. 최솟값을 갱신해줄 필요가 없다.

- DFS는 최단경로를 보장한다.

 

2. visited로 방문 여부를 판단할 필요가 없다.

- maps의 값이 1일 때만 방문하도록 하여 따로 방문 여부를 저장하는 배열이 필요하지 않다,

 

1. 문제 설명

양의 정수 n을 k 진수로 바꿨을 때, 변환된 수 안에 소수 (prime number)가 몇 개인지 알아보려고 한다.

 

- 0P0 : 소수 양쪽에 0이 있는 경우

- P0 : 소수 오른쪽에만 0이 있고, 왼쪽에는 아무것도 없는 경우

- 0P : 소수 왼쪽에만 0이 있고, 오른쪽에는 아무것도 없는 경우

- P : 소수 양쪽에 아무것도 없는 경우

 

예를 들어, 437674을 3진수로 바꾸면 211020101011이다.

소수는 211, 2, 11이므로 총 3개이다. 이때, 중복되는 원소에 대해서는 중복으로 세어준다.

 

 

 

2. 코드

(1) 1차 시도

def conversion(n, k):
    res = []
    
    while n > 0:
        res.append(str(n % k))
        
        n = n // k
    return ''.join(list(reversed(res)))

def is_prime(n):
    if n == 1:
        return False
    
    for i in range(2, n):
        if n % i == 0:
            return False
    
    return True
        
def solution(n, k):
    res = conversion(n, k)
    candidates = res.split('0')
    primes = 0
    
    for candidate in set(candidates):
        try:
            if is_prime(int(candidate)) == True:
                primes += candidates.count(candidate)
        except ValueError:
            continue
    
    return primes

 

 

(2) 2차 시도

def conversion(n, k):
    if k == 10:
        return str(n)
    
    res = ''
    
    while n > 0:
        n, mod = divmod(n, k)
        res += str(mod)
    
    return res[::-1]

def is_prime(n):
    if n == 1:
        return False
    
    for i in range(2, int(n ** (1/2)+1)):
        if n % i == 0:
            return False
    
    return True
        
def solution(n, k):
    res = conversion(n, k).split('0')

    primes = 0
    
    for candidate in set(res):
        try:
            prime_or_not = is_prime(int(candidate))
            
            if prime_or_not == True:
                   primes += res.count(candidate)
                   
        except ValueError:
            continue
        
    return primes

 

 

 

 

3. 설명

첫번째 시도 때에는 시간 초과가 발생해서, 최대한 줄일 수 있는 부분을 찾아서 고쳤다.

 

(1) conversion 함수

- 진수 변환에서 10진수인 경우에는 그대로 반환하기

- 진수 변환에서 직접 mod 연산과 몫 연산을 하기 보다는 divmod 함수 사용하기

- 리스트를 revered, join 하지 말고 string 타입으로 반환 시에는 [::-1]을 사용하여 역순으로 만들기

 

 

(2) is_prime 함수

- n까지 모두 다 검토하지 말고, n의 제곱근까지만 검토하기

 

 

(3) 동일한 코드

- 진수 변환한 문자열에 대해서 0을 기준으로 split 하기

- split한 문자열을 미리 정수로 바꾸지 말고, try ~ except를 사용해서 int로 바꿀 수 없는 문자열 (예. '')인 경우는 continue 해주기

- 동일한 문자가 존재할 수 있기 때문에 set을 사용해서 한번씩만 검토하되, count로 동일한 원소 개수를 정답에 더해주기

 

마포 한강나루에서 5km 러닝을 하고 왔다.

 

오늘 다행히도 비가 안 와서 오랜만에 달릴 수 있었음!

 

근데 습도가 너무 높아서 조금 달렸는데도 숨이 턱턱 막히는 느낌이었음ㅎㅎ

 

 

 

러닝을 시작한지 얼마 안 된 사람이라..ㅎㅎ

페이스에 집착하거나, 속도를 엄청 높이지는 않는다!

 

30분이 넘는 시간동안 쉬지 않고 달리는 것에 일단 의의를 두기 땜시롱..

 

 

그래도 6분대를 넘지 않도록 크루들이랑 같이 으쌰으쌰 했다!

 

 

다음주에는 서울 식물원에서 러닝을 할 계획이다.

러닝을 위해 체력을 더 단련해보겠다. 후후!

 

 

( 새벽에 머리가 너무 깨질듯이 아파서 타이레놀 두 정 먹고 다시 잤다. 같이 뛰었던 언니도 그 전날 러닝하고서 머리가 엄청 아팠다던데..

 

혹시 러닝이 두통을 유발하고 그러나..? 그 전까지는 괜찮았었는데 이번에만 그랬다ㅠㅠ

 

점점 날씨가 더워지고.. 뛸 날이 얼마 남지 않은 것 같긴 하다..ㅎㅎ)

+ Recent posts