https://www.acmicpc.net/problem/16918

 

16918번: 봄버맨

첫째 줄에 R, C, N (1 ≤ R, C, N ≤ 200)이 주어진다. 둘째 줄부터 R개의 줄에 격자판의 초기 상태가 주어진다. 빈 칸은 '.'로, 폭탄은 'O'로 주어진다.

www.acmicpc.net


풀이 과정


  1. 초기에 설치해둔 폭탄의 위치를 저장해 둔다.
  2. 폭탄이 없는곳에 모두 폭탄을 설치시켜 준다.
    • 이 때, 초기에 설치해둔 폭탄과 터지는 시간이 다르기 때문에 폭탄이 없는곳에 폭탄을 설치하면서 위치를 따로 저장해 두어야 한다.
  3. 직전에 설치한 폭탄이 아닌, 더 이전에 설치해둔 폭탄을 터트린다.
    • 이 때, 직전에 설치한 폭탄도 터질 수 있으므로 만약 직전에 설치한 폭탄도 터진다면 직전에 설치한 폭탄 집합에서 해당 폭탄을 제거해 준다.
  4. 입력받은 시간에 맞추어서 2-3 과정을 반복해 주면 된다.

소스 코드


import sys

input = lambda: sys.stdin.readline().rstrip()
R, C, N = map(int, input().split())

matrix = [list(input()) for _ in range(R)]
boompos = []
for i in range(R):
    for j in range(C):
        if matrix[i][j] == 'O':
            boompos.append([i, j])

def set_boom(matrix):
    next_boom = set()
    for i in range(R):
        for j in range(C):
            if matrix[i][j] == '.':
                next_boom.add((i, j))
                matrix[i][j] = 'O'
    return next_boom

def boom(matrix, boompos, next_boom):
    dx = [-1, 1, 0, 0]
    dy = [0, 0, 1, -1]
    destroypos = set()
    for x, y in boompos:
        destroypos.add((x, y))
        for i in range(4):
            nx, ny = x + dx[i], y + dy[i]
            if 0 <= nx and nx < R and 0 <= ny and ny < C:
                destroypos.add((nx, ny))

    for x, y in destroypos:
        if (x, y) in next_boom:
            next_boom.remove((x, y))
        matrix[x][y] = '.'
        

time = 1
while time < N:
    next_boom = set_boom(matrix)
    time += 1
    if time == N:
        break
    boom(matrix, boompos, next_boom)
    boompos = next_boom
    time += 1

for m in matrix:
    print("".join(m))

https://www.acmicpc.net/problem/17352

 

17352번: 여러분의 다리가 되어 드리겠습니다!

선린월드에는 N개의 섬이 있다. 섬에는 1, 2, ..., N의 번호가 하나씩 붙어 있다. 그 섬들을 N - 1개의 다리가 잇고 있으며, 어떤 두 섬 사이든 다리로 왕복할 수 있다. 어제까지는 그랬다. "왜 다리

www.acmicpc.net

 


풀이 과정


  1. 문제에서 다리를 하나 무너뜨려 서로 왕복할 수 없는 섬이 생겼다고 주어졌으므로 두개의 섬으로 분리되었다는걸 알 수 있음.
  2. Union-Find 알고리즘을 사용하여 두개의 섬의 집합을 구해준다.
    1. 이어진 섬의 parent는 같으며, 이어지지 않은 섬의 parent는 다르다는 점을 이용하여 1번째 섬에서부터 N번째 섬까지 방문하면서 인접한 섬과의 parent를 비교한다.
    2. parent 값이 다른 경우 떨어진 섬이므로 두 섬을 연결해주면 된다.

소스 코드


import sys

sys.setrecursionlimit(10**5)
input = lambda: sys.stdin.readline().rstrip()
N = int(input())
parent = [i for i in range(N+1)]


def find(parent, a):
    if parent[a] != a:
        parent[a] = find(parent, parent[a])
    return parent[a]

def union(parent, a, b):
    par1 = find(parent, a)
    par2 = find(parent, b)

    if par1 != par2:
        parent[par1] = par2

for _ in range(N-2):
    a, b = map(int, input().split())
    if find(parent, a) != find(parent, b):
        union(parent, a, b)

for i in range(2, N+1):
    if find(parent, i) != find(parent, i-1):
        union(parent, i, i-1)
        print(i, i-1)

https://www.acmicpc.net/problem/9440

 

9440번: 숫자 더하기

강민이가 초등학교 3학년일 때, 담임선생님이 이런 문제를 냈었다. 숫자 1, 2, 7, 8, 9 를 사용해서 만든 두 숫자를 더했을 때, 나올 수 있는 가장 작은 수는 무엇일까요? 강민이는 이 문제의 답이 2

www.acmicpc.net

 


풀이 과정


  1. 그리디 알고리즘 문제인데 처음 생각할 때 꼬여서 어떻게 풀어야 할지 고민을 정말 많이한 문제다ㅜ
  2. 숫자를 오름차순으로 정렬한다.
    1. 숫자들로 두개의 정수를 만들어야 하므로 a, b 리스트를 만들어 둔다.
    2. a, b 리스트에 번갈아가면서 작은 숫자부터 넣어준다.
    3. a, b 리스트에서 맨 앞에 넣을때는 0이 아닌 수중에 가장 작은 숫자를 넣어주어야 한다.
    4. 리스트에 채우는 작업이 종료되면, 두 리스트를 정수화하여 더해주면 된다.
  3. 더해준 값을 출력한다.

 소스 코드


import sys
from collections import deque, defaultdict

input = lambda: sys.stdin.readline().rstrip()
while True:
    p = list(map(int, input().split()))
    numbers = defaultdict(lambda: 0)
    if p[0] == 0:
        break
    
    for n in p[1:]:
        numbers[n] += 1
    
    a = []
    b = []
    flag = True
    for i in range(p[0]):
        target = None
        if flag:
            target = a
        else:
            target = b
        for j in range(10):
            if len(target) == 0 and j == 0:
                continue
            if numbers[j] > 0:
                numbers[j] -= 1
                target.append(j)
                break
        flag = not flag

    print(int("".join(map(str, a))) + int("".join(map(str, b))))

https://www.acmicpc.net/problem/17951

 

17951번: 흩날리는 시험지 속에서 내 평점이 느껴진거야

시험지를 12, 7, 19, 20과 17, 14, 9, 10 으로 나누면 맞은 문제 개수의 합의 최소는 50이다.

www.acmicpc.net

 


풀이 과정


  1. 그룹의 맞은 문제의 합의 최솟값을 기준으로 이분탐색을 진행한다.
  2. 초기 left를 1, right를 10**5 * 20 + 1로 둔다. 이유는 최소 점수는 1점이고 최대 점수는 그룹이 1개이면서 시험지의 개수가 10**5개이며 각 시험지에서 맞은 문제가 모두 20개일 수 있기 때문이다.
  3. 중간값((left + right) // 2)에 대해서 몇개의 그룹이 나오는지 확인한다.
    • 맞은 개수를 더해가면서 중간값보다 커진다면 그룹의 개수를 하나 늘려주고 맞은 개수 초기화
  4. 전체 그룹의 개수가 K개보다 많다면 해당 점수로 나눌 수 있는 것이므로 따로 저장 후 오른쪽 구간 진행
  5. 전체 그룹의 개수가 K개보다 적다면 해당 점수로 나눌 수 없는 것이므로 왼쪽 구간 진행
  6. 따로 저장해둔 정답을 출력시켜 준다. 

소스 코드


import sys

input = lambda: sys.stdin.readline().rstrip()
N, K = map(int, input().split())
paper = list(map(int, input().split()))

left = 1
right = (10 ** 5 * 20) + 1

answer = 0
while left <= right:
    mid = (left + right) // 2
    group_count = 0
    score = 0
    for p in paper:
        score += p
        if score >= mid:
            group_count += 1
            score = 0

    if group_count < K:
        right = mid - 1
    else:
        answer = mid
        left = mid + 1

print(answer)

https://www.acmicpc.net/problem/23843

 

23843번: 콘센트

광재는 전자기기 대여사업을 시작했다. 퇴근하기 전에 다음날 손님들에게 빌려줄 N개의 전자기기를 충전하려 한다. 사용 가능한 콘센트는 M개가 있고, 성능은 모두 동일하다. 전자기기들은 한

www.acmicpc.net

 


풀이 과정


  1. 시간이 오래 걸리는 전자 기기부터 충전시키는 방식으로 진행
  2. 시간을 계산하기 위해서는 최소 히프를 사용해 준다.
    1. 히프에 현재 충전중인 전자 기기가 걸리는 시간을 넣어 준다.
    2. 히프가 가득 차지 않은 경우에는 충전기 자리가 남아있는 것이므로 전자기기의 충전 시간을 그대로 넣어준다.
    3. 히프가 가득 찬 경우는 충전기가 꽉 찬 경우이므로 기기를 하나 빼준 다음에 넣어주어야 한다. 따라서 히프에서요소 하나를 빼준 후, 해당 요소의 값에 현재 전자기기의 충전 시간을 더해서 다시 히프에 넣어준다.
  3. 히프 내의 최댓값을 구해서 출력시켜 준다. 
    • 히프 내의 최댓값이 의미하는 것은 마지막으로 충전이 완료되는 시간이다.

소스 코드


import sys
import heapq

N, M = map(int, input().split())
elec = list(map(int, input().split()))
elec.sort(reverse=True)
heap = []

for e in elec:
    if len(heap) < M:
        heapq.heappush(heap, e)
    else:
        outcome = heapq.heappop(heap)
        heapq.heappush(heap, outcome + e)

print(max(heap))

https://www.acmicpc.net/problem/21276

 

21276번: 계보 복원가 호석

석호촌에는 N 명의 사람이 살고 있다. 굉장히 활발한 성격인 석호촌 사람들은 옆 집 상도 아버님, 뒷집 하은 할머님 , 강 건너 유리 어머님 등 모두가 한 가족처럼 살아가고 있다. 그러던 어느 날

www.acmicpc.net

 


풀이 과정


  1. 이름과 연결된 자식들의 정보를 저장해 둔다.
    • 자식-(부모 or 조상)이 연결되어 있다면, 자식의 진입차수를 1 증가시켜 준다.
    • 단, 여기서 부모가 조상일수도 있음.
  2. 초기 큐에는 각 가문의 시조들을 저장해 둔다.
    • 진입차수가 0인 이름들이 각 가문의 시조들이다.
  3. 큐에서 한명씩 빼주면서 연결된 자식들의 진입차수를 1씩 감소시킨다.
    1. 진입차수가 0이 된다면, 해당 자식은 직전에 큐에서 빼준 인원의 자식이기 때문에 따로 저장해 두고, 해당 자식은 큐에 삽입하여 준다.
  4. 출력 형식에 맞추어서 출력시켜주면 된다.

소스 코드


import sys
from collections import deque

input = lambda: sys.stdin.readline().rstrip()
N = int(input())
people = set(input().split())
child = {person:[] for person in people}
edge = {person:[] for person in people}
indegree = {person:0 for person in people}
father = []

M = int(input())
for _ in range(M):
    a, b = input().split()
    indegree[a] += 1
    edge[b].append(a)
    
queue = deque()
for person in people:
    if indegree[person] == 0:
        queue.append(person)
        father.append(person)
        
while queue:
    node = queue.popleft()
    for next_node in edge[node]:
        indegree[next_node] -= 1
        if indegree[next_node] == 0:
            queue.append(next_node)
            child[node].append(next_node)

print(len(father))
print(*sorted(father))
for name in sorted(list(people)):
    print_str = name + " " + str(len(child[name]))
    if len(child[name]) != 0:
        print_str += (" " + " ".join(sorted(child[name])))
    print(print_str)

 

https://www.acmicpc.net/problem/1766

 

1766번: 문제집

첫째 줄에 문제의 수 N(1 ≤ N ≤ 32,000)과 먼저 푸는 것이 좋은 문제에 대한 정보의 개수 M(1 ≤ M ≤ 100,000)이 주어진다. 둘째 줄부터 M개의 줄에 걸쳐 두 정수의 순서쌍 A,B가 빈칸을 사이에 두고 주

www.acmicpc.net


풀이 과정


  1. 문제를 푸는 순서가 있으므로 위상정렬 방식으로 풀이하는것이 좋음. 단, 문제 난이도가 낮은 것(번호가 작은 것)부터 풀어야 하므로 최소 히프를 사용하여서 구현함.
  2. 문제들의 연결 정보와 각 문제의 진입 차수를 따로 저장한다.
  3. 초기에 진입 차수가 0인 문제들을 히프에 넣는다.
  4. 히프에서 문제 하나를 꺼내고, 문제에 연결된 다른 문제들(해당 문제를 푼 다음에 풀 문제들)의 진입차수를 하나 낮추어 준다.
    1. 이 때, 진입차수가 0이 된다면 해당 문제 번호를 히프에 넣어준다.
    2. 히프에서 문제를 꺼낼 때 따로 리스트에 문제 번호를 저장해주어야 함.(정답에서 출력)

소스 코드


import heapq
import sys

input = lambda: sys.stdin.readline().rstrip()
n, m = map(int, input().split())

graph = [[] for _ in range(n+1)]
indegree = [0] * (n+1)
for _ in range(m):
    a, b = map(int, input().split())
    graph[a].append(b)
    indegree[b] += 1

solve = []
heap = []

for i in range(1, n+1):
    if indegree[i] == 0:
        heapq.heappush(heap, i)

while heap:
    problem_number = heapq.heappop(heap)
    solve.append(problem_number)
    for next_problem in graph[problem_number]:
        indegree[next_problem] -= 1
        if indegree[next_problem] == 0:
            heapq.heappush(heap, next_problem)

print(*solve)

https://programmers.co.kr/learn/courses/30/lessons/86053?language=python3 

 

코딩테스트 연습 - 금과 은 운반하기

어느 왕국에 하나 이상의 도시들이 있습니다. 왕국의 왕은 새 도시를 짓기로 결정하였습니다. 해당 도시를 짓기 위해서는 도시를 짓는 장소에 금 a kg과 은 b kg이 전달되어야 합니다. 각 도시에는

programmers.co.kr

 


풀이 과정


  1. 걸리는 시간의 범위가 크기 때문에 전체 범위가 너무 커질것 같아 이분탐색을 고려하였으나 이분 탐색 시 시뮬레이션 하는 파트 생각이 안나서 게시된 문제 풀이를 참조함.
  2. 현재 시간을 t분이라고 할 때
    1. t분동안 물건을 나르는 횟수는 크게 mid // (걸리는 시간 * 2)이고, 맨 마지막에 편도로 이동 가능하므로 mid % (걸리는 시간 * 2)가 걸리는 시간보다 큰 경우는 횟수를 하나 늘려준다.
    2. t분동안 각각의 도시에서 옮길 수 있는 최대 금, 최대 은 개수를 각각 더해준다.
    3. 동시에 각각의 도시에서 옮길 수 있는 광물의 수의 총합도 구해준다.
    4. 다음 조건이 만족하면 정답을 저장하고 왼쪽 구간을, 아니라면 오른쪽 구간을 진행한다.
      1. 옮길수 있는 최대 금의 개수가 a보다 큰지
      2. 옮길수 있는 최대 은의 개수가 b보다 큰지
      3. 각각의 도시에서 옮길수 있는 광물의 수의 합이 a+b보다 큰지
    5. 잘 생각해 보면, 옮길 수 있는 광물의 수의 합이 a+b보다 크고, 최대 금과 최대 은의 개수가 a, b보다 크다면 금과 은의 개수를 적절하게 맞추어 준다면 금 a kg 이상, 은 b kg 이상을 나를 수 있다.
  3. 시뮬레이션 파트를 잘 생각하지 못해서 풀지 못했던 문제임.. 고민 많이 해볼것.

소스 코드


def solution(a, b, g, s, w, t):
    answer = int(10**16)
    left, right = 0, int(10**16)
    
    while left <= right:
        mid = (left + right) // 2
        gold = 0
        silver = 0
        total = 0
        for i in range(len(g)):
            movement_count = mid // (t[i] * 2)
            if mid % (t[i] * 2) >= t[i]:
                movement_count += 1
            city_gold = w[i] * movement_count if w[i] * movement_count <= g[i] else g[i]
            city_silver = w[i] * movement_count if w[i] * movement_count <= s[i] else s[i]
            gold += city_gold
            silver += city_silver
            total += w[i] * movement_count if s[i] + g[i] >= w[i] * movement_count else s[i] + g[i]

        if gold >= a and silver >= b and total >= a + b:
            right = mid - 1
            answer = min(answer, mid)
        else:
            left = mid + 1
        
    return answer

https://leetcode.com/problems/longest-palindromic-substring/submissions/

 

Longest Palindromic Substring - LeetCode

Level up your coding skills and quickly land a job. This is the best place to expand your knowledge and get prepared for your next interview.

leetcode.com


풀이 과정


  1. DP로 풀이하는게 정석이라고 하지만 문자열 최대 길이가 1000이므로 브루트포스로 풀수 있을것이라고 생각함.
  2. 현재 위치가 i라고 하면, i 기준으로 문자를 하나씩 늘려가면서 펠린드롬이라면 문자열을 갱신하는 방식으로 코드 작성
    1. 시간 초과가 발생. 시간을 조금 절약하기 위해 정답 문자열의 길이 + 1부터 문자를 하나씩 늘려가도록 변경
    2. 위 방식으로 코드를 작성하니 시간 초과가 해결됨. 

소스 코드


class Solution:
    def longestPalindrome(self, s: str) -> str:
        answer = ""
        def checkPalindrome(s):
            return s == s[::-1]
        
        for i in range(len(s)):
            for j in range(len(answer)+1, len(s)-i+1):
                if checkPalindrome(s[i:i+j]):
                    answer = s[i:i+j] if len(answer) < j else answer
                    
        return answer

https://www.acmicpc.net/problem/2533

 

2533번: 사회망 서비스(SNS)

첫 번째 줄에는 친구 관계 트리의 정점 개수 N이 주어진다. 단, 2 ≤ N ≤ 1,000,000이며, 각 정점은 1부터 N까지 일련번호로 표현된다. 두 번째 줄부터 N-1개의 줄에는 각 줄마다 친구 관계 트리의 에

www.acmicpc.net


풀이 과정


  1. 아무 점이나 루트로 잡아서 진행한다.
  2. 현재 점에 연결된 방문하지 않은 모든 점들을 방문하면서 DP테이블을 갱신한다.
    1. 초기 모든 DP테이블은 점마다 [0, 1]로 설정한다.  
    2. DP[i][0]은 루트가 i점인 부분 트리에서 i점이 얼리어답터가 아닐 때의 전체 얼리어답터 최소 개수
    3. DP[i][1]은 루트가 i점인 부분 트리에서 i점이 얼리어답터일 때의 전체 얼리어답터 최소 개수
    4. 따라서, DP[i][0]은 다음 점에서는 얼리어답터가 나와야 하므로 DP[다음 점][1]을 더해준다.
    5. DP[i][1]은 다음 점에서 얼리어답터가 나올수도 있고 나오지 않을수도 있으므로 DP[다음 점][0]과 DP[다음 점][1]의 최솟값을 더해 준다.
  3. 루트 노드에서의 DP 테이블의 최솟값을 출력시켜준다.

소스 코드


import sys

sys.setrecursionlimit(10**6)

input = lambda: sys.stdin.readline().rstrip()

n = int(input())
tree = [[] for _ in range(n+1)]

for _ in range(n-1):
    src, dest = map(int, input().split())
    tree[src].append(dest)
    tree[dest].append(src)

root = 1

dp = [[0, 1] for _ in range(n+1)]
visited = [False] * (n+1)

def solve(node):
    visited[node] = True
    for next_node in tree[node]:
        if not visited[next_node]:
            solve(next_node)
            dp[node][0] += dp[next_node][1]
            dp[node][1] += min(dp[next_node][0], dp[next_node][1])
        

solve(root)
print(min(dp[root]))

+ Recent posts