N,K = map(int,input().split())
N += 1
N_list = list(str(N))
cur_idx = -1
max_idx = len(N_list)
while True:
    if N_list.count('5') >= K:
        break
    while N_list[cur_idx] == '5' and abs(cur_idx) < max_idx:
        cur_idx -= 1
    
    cur_value = int(''.join(N_list))
    cur_value = cur_value + 10**(abs(cur_idx)-1)
    N_list = list(str(cur_value))
    max_idx = len(N_list)



print(''.join(N_list))

 

 

이 문제는 간단하다. 가장 뒤에서부터 5를 만들어주면 되는것이다. 

 

여기서 주의해야할 점은 다음과 같은 경우이다. K가 1이고, 주어진 N이 48이였을때

 

우리는 49부터 탐색을 시작하게 되는데, 그때 50이 되면 K를 만족하는 수가 된다.

 

그러므로 우리는 5가 아닌 자리수부터 1씩 늘려가면서, 가장 오른쪽 자리부터 5를 만들어줘야한다.

 

그래서 나는 cur_idx 라는것을 뒤에서부터 접근하기 위해 -1로 해주었고, 

 

abs(cur_idx) - 1을 해주면 해당 자릿수를 구할 수 있다. 즉 첫번째 자리는 1이 더해지게, 오른쪽에서 두번째자리는 10,

 

세번째 자리는 100이 더해지게 만들어주는 것이다.

 

이럴때 주의해야할 점은 999일때이다. 999에서 1을 더해주면 1000이된다. 그러면 우리의 idx가 넘어가게 되므로,

 

max_idx를 새로 계속 갱신을 해주었다.

 

그리고 555 이고, 구하는 K가 4일때를 대비해서 while문에 abs(cur_idx)<max_idx 를 넘어갈때를 escape 해주었다.

 

이런식으로 오른쪽 자리수부터 1씩 더해가면서 5를 만들어주고, 그리고 count를 해서 넘어가면

 

반복문을 빠져 나올 수 있게 해주었다.

 

 

여담으로 문제 제목이 직관적이고, 가장 짧은 문제였던 것 같다.

import sys
from collections import deque

input = sys.stdin.readline


N,M = map(int,input().split())
graph = [set() for _ in range(N+1)]
degree = [0 for _ in range(N+1)]
for _ in range(M):
    pdN,*arr = list(map(int,input().split()))

    for i in range(pdN-1):
        x,y = arr[i],arr[i+1]
        if y not in graph[x]:
            graph[x].add(y)
            degree[y] += 1

stack = deque()
cnt = 0
result = []
flag = True

for i in range(1,N+1):
    if degree[i]==0:
        stack.append(i)
while cnt<N:
    if not stack:
        flag = False
        break
    node = stack.popleft()
    result.append(str(node))
    for next_node in graph[node]:
        degree[next_node] -= 1

        if degree[next_node] == 0:
            stack.append(next_node)
    cnt += 1

if flag:
    print('\n'.join(result))
else:
    print(0)

이 문제와 같은 경우 평범한 위상정렬이다.

 

여러명의 PD를 통해 앞에서부터, 하나씩 그래프에 SET으로 넣어주었다.

 

그리고 degree가 0인것들은 최초의 stack에 넣어주고 난뒤에 위상정렬을 구해주면서,

 

사이클이 발생할 시, 음악프로그램을 구할 수 없는 것이므로, 그때 flag로 분기 처리를 해주었다.

 

그리고 stack에 나온순서대로 result에 넣어주고 출력을 해주었다.

A,B = map(int,input().split())


if A>B:
    A,B = B,A

X,Y = map(int,input().split())
result = []
flag = True
if Y>=abs(X) or Y<0:
    flag = False
if flag:
    X = abs(X)
    value = X*(A//X)+Y
    while value<=B:
        if A<=value<=B:
            if result:
                flag = False
                break
            result.append(value)
        value += X
if flag and result:
    print(*result)
else:
    print('Unknwon Number')

  이 문제에서 주의해야할 점은 Y가 X보다 큰게 들어올수도 있으며, 0 미만일수도 있다.

 

그럴 경우엔 False를 해주고, A,B가 서로 반대로 들어올 수 있는것만 조심해주면 된다.

 

A~B 사이에서 생길수 있는 최소의 X,Y로 만들수 있는 수를 찾는다.

 

그리고 난뒤에 X를 늘려가면서, 2개이상의 수가 있을때에는 flag로 Unkwon Number를 출력해주면 된다.

A,B = map(int,input().split())


if A>B:
    A,B = B,A

X,Y = map(int,input().split())

X = abs(X)
left_div = A//X
right_div = (B+X)//X
result = []
flag = True
if Y>=abs(X) or Y<0:
    flag = False
if flag:
    for div in range(left_div,right_div+1):
        temp = div*X+Y
        if A<=temp<=B:
            if result:
                flag = False
                break
            else:
                result.append(temp)


if flag and result:
    print(*result)
else:
    print('Unknwon Number')

 

이건 반복문을 통해서 구현한 것이다.

 클래스 5 문제들을 풀어서 클래스 점수로 플레4에 도달하긴했다..

 

플레4는 6월1일에 찍었다.

 

 

찾아보니 3월9일에 골드1 달성

 

4월 29일에 플레5달성

 

6월 1일에 플레4를 달성했다.

 

느리지만 천천히 꾸준히 문제를 푼것같다.

 

1월부터 하루 1일 1알고를 한번도 빼먹은적이 없다보니, 푼 문제수가, 직선그래프처럼 그려지긴했다.

 

플레 3은 갈 가능성은 적지만, 세그먼트 트리나 트리쪽을 더 공부해서 도전은 해보고 싶긴하다.

 

근데 사실 아직 이분탐색과, 두포인터, 위상정렬 관련된 문제가 나오면 죽쓰는것보면 기초에 대해서 더 열심히 공부해야할 것 같다.

'주절주절' 카테고리의 다른 글

[BOJ/백준] 플레3 달성?  (0) 2021.11.09
글이 뜸한 이유  (0) 2021.08.20
[백준] 플레 5 달성  (0) 2021.04.30
백준 골드1 달성  (0) 2021.03.11
백준 150문제 돌파.  (0) 2021.02.18
import sys
input = sys.stdin.readline
INF = (10**12)+1

def get_process(mid_priority):
    global N
    if dp.get(mid_priority):
        return dp[mid_priority]
    else:
        total_process_cnt = 0


        for i in range(N):
            process = arr[i]

            if mid_priority<=process.sp:
                total_process_cnt += process.time
            elif process.sp< mid_priority<=process.ep:
                total_process_cnt = total_process_cnt + process.ep - mid_priority +1
        
        dp[mid_priority] = total_process_cnt
        return total_process_cnt


def b_search(target_T):
    left = 0
    right = INF*2
    while left<=right:
        mid = (left+right)//2
        total_cnt = get_process(mid)
        if total_cnt>=target_T:
            next_priority_cnt = get_process(mid+1)
            if next_priority_cnt<target_T:
                remain_priority_cnt = target_T - next_priority_cnt
                for i in range(N):
                    if arr[i].sp <= mid <=arr[i].ep:
                        remain_priority_cnt -= 1
                        if remain_priority_cnt == 0:
                            result.append(arr[i].process_id)
                            break
                break
            else:
                left = mid + 1

        else:
            right = mid-1


class Process:
    def __init__(self,_id,_spend_time,_init_priority):
        self.process_id = _id
        self.time = _spend_time
        self.ep = _init_priority+INF
        self.sp = _init_priority+INF-spend_time+1


Q,N = map(int,input().split())
arr = []
for _ in range(N):
    process_id,spend_time,init_priority = map(int,input().split())
    new_process = Process(process_id,spend_time,init_priority)
    arr.append(new_process)
dp = {}
arr.sort(key=lambda x : x.process_id)
result = []

for _ in range(Q):
    find_time = int(input())

    b_search(find_time)


for i in range(Q):
    sys.stdout.write(str(result[i])+'\n')

 

 

이 문제 또한 앞선 문제와 같이 혼자서 풀기 어려운 난이도라, https://github.com/cdog-gh/gh_coding_test 해설을 보고 푼 문제이다.

 

이 문제는 boj.kr/21773 과 boj.kr/21777 문제를 이해해야지만 풀 수 있는 문제였다.

 

앞서 21777에서 말한것처럼  초기 priority가 P라 하고, 총 실행시간이 T라한다면,

 

 

P~ (P-T+1) 까지 우선순위를 실행하게 될 것이다.

 

그러므로 우리는 무지하게 큰 초기값을 각각의 priorty에 더해준다. 왜냐하면, 양수의 priority로만 구분을 해주기 위함이다.

 

 

그러므로 INF + P 를 end_priority 그리고 INF + P - T + 1 를 start_priority 로 해주었다.

 

 

근데 숫자가 커서 end_priority와 start_priority라 했지만, 이 문제를 더 쉽게 이해하기 위해선 반대로 바꾸는것도 한다.

 

왜냐하면 우선순위가 클수록 먼저 실행이 되기 때문이다.

 

그러면 우리는 시간 T를 찾는것이다.

 

시간 T를 찾는 방법은 다음 과 같다. 특정 priority일때까지 실행된 모든 프로세스의 개수를 세주는 것이다.

 

priority가 실행된 개수가 곧 실행시간이기 때문이다.

 

여기서 주의해야할점은 get_process(priority) == T 를 만족하는 priority가 많을 것이다.

 

그러므로, 우리는 priority가 현재보다 1이 커졌을때 T보다 작아지는 경우를 찾아야,

 

구하고자하는 실행시간 T에 실행되는 process를 찾을 수 있다.

 

나머지는 이분탐색처럼 하면 되는데 여기서 주의해야할점은 다음과 같다.

 

 

priority가 높을수록 일찍 실행되고, 낮을수록 늦게 실행된다.

 

만약 K라는 priorty까지 실행되는 priority의 개수를 구해야한다면,

 

K <= start_priority 와 같다면, 이 process_id가 가진 모든 실행시간을 쓴 것이기 때문에 전부 더해주면 된다.

 

그리고 start_priority < K <= end_priority 일때에는

 

end_priority - K + 1까지가 프로세스가 실행된 것이기 때문에 이 부분을 더해주면 된다.

 

 

마지막으로, 우리가 구한 get_process(mid_priority) >= T  와 get_process(mid_priority+1)<T를

 

만족하는 mid_priority에서 실제로 실행된 priority를 구해야한다.

 

get_process(mid_priority)  - get_process(mid_priority+1) 을 빼준값을 remain_priority_cnt라 하고

 

id 1부터 해서 mid_priorty가 해당 프로세스의 start_point와 end_point 사이에 있으면  이 값을 한개씩 줄여주면서 

 

 

0이 되었을때 실제로 실행된 process_id이므로 그때의 process_id를 출력해주면 된다.

 

그리고, get_process에서 특정 process에 대한 total_cnt는 동일할것이기 때문에 캐싱을 해주면 된다.

 

또한 dp테이블로 만든게 아닌, 함수이므로, functools의 lru_cahce를 이용하는 방법도 있다.

 

import sys

input = sys.stdin.readline
N = 1000001
max_priority = N//10
T = int(input())
INF = float('inf')
start_process_time = [INF]*N
end_process_time = [0]*N
arr = list(map(int,input().split()))
mono_times = 1
prev_process = -1
for i in range(T):
    cur_process = arr[i]
    if prev_process >= cur_process:
        mono_times += 1

    start_process_time[cur_process] = min(start_process_time[cur_process],mono_times)
    end_process_time[cur_process] = max(end_process_time[cur_process],mono_times)
    prev_process = cur_process


active_process_list = []
for i in range(N):
    if end_process_time[i]:
        active_process_list.append(i)



result = []
for process_id in active_process_list:
    priority = max_priority-1-start_process_time[process_id]
    spend_time = end_process_time[process_id]-start_process_time[process_id] + 1
    result.append((str(process_id),str(spend_time),str(priority)))


sys.stdout.write(str(len(active_process_list))+'\n')


for i in range(len(active_process_list)):
    sys.stdout.write(' '.join(result[i])+'\n')

 

이 문제 부터는 사실상 저 혼자만의 힘으로 푼 것이 아닌, 코딩개(chogahui05)님의 해설을 보고,

 

푼 것이기 때문에 온전한 실력이라고 할수 없고, 정확한 설명은 아래 링크를 참조하시길 바랍니다.

 

https://github.com/cdog-gh/gh_coding_test

 

cdog-gh/gh_coding_test

gahui_coding_test. Contribute to cdog-gh/gh_coding_test development by creating an account on GitHub.

github.com

 

이 문제는 가희배 3번 문제 boj.kr/21773 의 연장선상이라고 보면 됩니다.

 

여기서는 실행된 프로세스 목록을 보고 프로세스의 우선순위와 실행시간을 구하는 문제입니다.

 

 

위의 설명에서도 잘 나와있듯이, 이 문제는 순증가수열별로 나누면 됩니다.

 

 

왜냐하면, 이 문제에서 먼저 같은 우선순위이면, 무조건 id가 적은것부터 나오게 됩니다.

 

그러므로 순증가수열 내에 있는 id들은 같은 우선순위로 시작하는 것을 알 수 있습니다.

 

그래서, 최초로 실행되는 위치이후로는 작업이 끝날때까지 매번 실행이 될것이기 때문에, 최초의 순증가 수열의 위치가

 

중요합니다.

 

그래서 여기서 구해야할것은 최초 프로세스가 실행되는 순증가수열의 최초의 위치,

 

그리고 프로세스가 마지막으로 실행되는 순증가수열의 마지막 위치, 이 두가지가 중요합니다.

 

만약 마지막 순증가수열의 프로세스 위치를 E 그리고 최초의 순증가 수열의 최초의 위치가 S라 하면

 

 

작업시간은 E - S + 1이 된다. 그리고 이 문제의 최대시간은 10^5이므로, 최대 priority 는 10^5+1로 설정을 하고, 

 

그 최대값에서 최대 priority - S를 해주면 된다.

 

 

 

# jthis님 풀이

import sys

input = sys.stdin.readline
N = int(input())
process_state = [[0 for _ in range(2)] for _ in range(1000001)]
# 0번 인덱스 총 시간
# 1번 인덱스 우선순위
arr = list(map(int,input().split()))

total_process = 0
for i in range(N):
    cur_process = arr[i]
    if not process_state[cur_process][0]:
        total_process += 1
    process_state[cur_process][0] += 1
 


pre_priority = 1
last_value = arr[-1]
process_state[last_value][1] = 1

for i in range(N-2,-1,-1):
    cur_process = arr[i]
    if not process_state[cur_process][1]:
        # 처음 나왔을때
        if cur_process<last_value:
            process_state[cur_process][1] = pre_priority
            # 이후의 값보다 낮은 값이면, 같은 순증가이므로, 같은 우선순위
        else:
            process_state[cur_process][1] = pre_priority + 1
    else:
        process_state[cur_process][1] += 1

    
    pre_priority = process_state[cur_process][1]
    last_value = cur_process


sys.stdout.write(str(total_process)+'\n')

for i in range(1000001):
    if process_state[i][0]:
        sys.stdout.write(str(i)+' '+str(process_state[i][0])+' '+str(process_state[i][1])+'\n')

 이 방식은 앞선 방식과 뒤에서부터 찾아가는 방식이다. 

 

먼저 전체 실행시간은 반복문을 돌리면서 총 시간을 더해준다.

 

그리고 이 문제에서 쓰는 프로세스의 종류는 total_process를 통해 구해준다.

 

이 문제도 같은 순증가 수열에 있는건지 확인을 해주는 방식이다.

 

이 문제의 우선순위가 낮은것부터 제일 뒤에서부터 실행되는 것을 응용한 것이다.

 

 

가장 마지막에 실행되는 것은 일단 가장 우선순위가 낮은 1일 것이다.

 

그리고 그때의 process_id보다 그이전의 process_id가 낮다는 것은 같은 순증가수열에 있고,

 

같은 우선순위 그룹에 잇는 것임을 알 수 있다. 그러므로 최초의 우선순위를 같게 설정을 해주면 된다.

 

그런데 만약 이전 process_id가 더 크거나 같으면, 다른 순증가 수열에 있는 것이므로,

 

현재 우선순위보다 1을 높여줘야한다.

 

그리고 최초로 만난 프로세스가 아니라면, 이미 자기의 초기 우선순위를 알고 있으므로, 1씩 증가시켜 주면 된다.

 

이 문제는 프로세스의 수행시간이 어떻게 되는지, 우선순위가 어떻게 구성되는지에 대해서

 

알아야 풀 수 있는 문제인것같다.

 

 

import sys
input = sys.stdin.readline
def permutation(ind,C,string_list,particle_order):
    global result
    if ind == C:
        if len(string_list)>0:
            result.add(''.join(string_list))
        else:
            result.add('EMPTY')
        return
    else:
        for i in range(1,N+1):
            command_order = particle_order[i]
            if command_order >= len(order_list[i]):
                continue
            else: 
                if not visited[i][command_order]:
                    order_num = order_list[i][command_order]
                    new_stringlist = string_list[:]
                    check_error = False
                    for order in card_command[order_num]:
                        if order[0] == 'ADD':
                            new_stringlist.append(order[1])
                        else:
                            remove_index = int(order[1])
                            if len(new_stringlist) > remove_index:
                                new_stringlist.pop(remove_index)
                            else:
                                check_error = True
                                break
                    if check_error:
                        result.add('ERROR')
                        continue
                    else:
                        visited[i][command_order] = True
                        particle_order[i] += 1
                        permutation(ind+1,C,new_stringlist,particle_order)
                        visited[i][command_order] = False
                        particle_order[i] -= 1


N,C = map(int,input().split())

order_list = [[] for _ in range(N+1)]

for ind in range(1,N+1):
    input_list = list(map(int,input().split()))
    order_list[ind] = input_list[1:]



card_command = [[] for _ in range(C+1)]


for ind in range(1,C+1):
    commands = list(input().rstrip().split(','))
    temp = []
    for command in commands:
        new_command = list(command.split(' '))
        temp.append(new_command)
    card_command[ind] = temp

result = set()
visited = [[False for _ in range(len(order_list[ind]))] for ind in range(N+1)]
particle_order = [0 for _ in range(N+1)]
permutation(0,C,[],particle_order)
result = list(result)
result.sort()
for i in range(len(result)):
    sys.stdout.write(result[i]+'\n')

이 문제는 구현을 하면 되는 문제였다. 여기서 주의해야할 점은, 사람1이 소지한 순서대로 카드를 낸다는것이다.

 

그러므로 먼저 사람1~ 사람N 까지의 순열을 구하는데 느낌은 

 

사람이 가지고 있는 카드의 수만큼 중복되게 수를 구해주고 순열을 구해주는 느낌으로 풀면된다.

 

만약 사람1이 카드를 4장 사람2가 카드를 2장 사람3가 카드를 3장 가지고 있다고 하면

 

[1,1,1,1,2,2,3,3,3] 이런식으로 리스트를 만들어놓고 순열을 구해도 된다.

 

나 같은 경우엔 각 사용자별로 card_command에 각 명령어를 파싱해서 저장을 시켜주었다.

 

그리고 particle_order를 이용해서, 각 사용자가 몇번재 카드를 썼는지 확인을했다.

 

그 뒤에는 재귀를 이용해서 백트래킹을 해주었다.

 

particle_order의 숫자가 사람1의 전체 명령어 수와 같게 되면, 선택을 못하게 if문으로 판별을 해주었다.

 

prarticle_order가 각 사람의 명령어 수보다 적다면, 인제 이 명령어가 가능한지 판단을 한다.

 

명령을 수행하다가 error가 발생시, result에 add를 추가해주고, 다음번으로 넘어가준다.

 

그리고 명령을 정확하게 수행하면, visited[사람의 인덱스][그 사람의 몇번째 카드]에 방문을 표시를 해준다.

 

그리고 particle_order의 값을 1 늘려주고, 재귀를 해준다.

 

이렇게 재귀를 하면서 전체 카드수를 다 쓰면, 모든 명령을 잘 수행한것이 된다. 그러면 그때의 결과를 result에 추가하는데,

 

아무것도 안남아있으면 EMPTY를 추가해주면 된다.

 

그리고 재귀를 하다가 복귀하게 되었을때에는 visited를 초기화해주고, particle_order도 1을 빼주면 된다.

 

 

이 문제는 백트래킹을 어떻게, 그리고 순열을 어떻게 응용해서 하는지에 대한 문제였다.

 

그래서 긴 문제 지문에 비해 많이 어려운 편은 아니였다.

import sys
from collections import deque
input = sys.stdin.readline



N,T = map(int,input().split())

order_list = list(map(int,input().split()))

stack_list = [[[],set()] for _ in range(N+1)]
card_deck = deque()
result = []
for _ in range(T):
    input_list = list(input().split())
    card_deck.append(input_list)

num_occupy_set = set()
for ind in order_list:
    if len(stack_list[ind][0]) > 0:
        cu_card = stack_list[ind][0][0]
        result.append(cu_card[0])
        if cu_card[2] in num_occupy_set:
            continue
        else:
            stack_list[ind][0].pop(0)
            stack_list[ind][1].add(cu_card[2])
            num_occupy_set.add(cu_card[2])

    else:
        cu_card = card_deck.popleft()
        result.append(cu_card[0])

        if cu_card[1] == 'next':
            continue
        elif cu_card[1] == 'acquire':
            if cu_card[2] in num_occupy_set:
                stack_list[ind][0].append(cu_card)
            else:
                stack_list[ind][1].add(cu_card[2])
                num_occupy_set.add(cu_card[2])
        else:
            stack_list[ind][1].remove(cu_card[2])
            num_occupy_set.remove(cu_card[2])

for i in range(T):
    sys.stdout.write(result[i]+"\n")

문제에 주어진대로 사람 수대로, deck을 만들어준뒤, 순서대로 명령어를 실행해주면 되는 구현 문제였다.

 

만약에 acquire 카드를 썼지만, 카드더미에 없으면, 자기 덱에 카드를 넣어주고, 그 카드를 다시 실행해주는 구현부분만 제대로 해주면 된다.

 

 이 코드는 깔끔하지 못해서 대회가 끝나고 난뒤에 고친 코드는 밑에 있다.

import sys
from collections import deque
input = sys.stdin.readline
N,T = map(int,input().split())

turns = list(map(int,input().split()))



card_deck = deque()

for _ in range(T):
    temp = input().rstrip().split(' ')
    card_deck.append(temp)

occupy_card = [[] for _ in range(N+2)]
result = []
used_card_num = set()
for i in range(T):
    person = turns[i]

    if len(occupy_card[person])>0:
        card_num,wanted_num = occupy_card[person]
        result.append(card_num)
        if wanted_num in used_card_num:
            continue
        else:
            used_card_num.add(wanted_num)
            occupy_card[person] = []
    else:
        card_num,*rests= card_deck.popleft()
        result.append(card_num)
        if rests[0] == 'next':
            continue
        elif rests[0] == 'acquire':
            if rests[1] in used_card_num:
                occupy_card[person] = (card_num,rests[1])
            else:
                used_card_num.add(rests[1])
        elif rests[0] == 'release':
            used_card_num.remove(rests[1])


for i in range(T):
    sys.stdout.write(result[i]+'\n')

어차피 보유하고 있을수 있는 카드는 한장이므로,  set을 굳이 넣을 필요가 없고, used_card를 통해, 쓴 카드와 안쓴 카드를 구분을 해줬다.

 

 

+ Recent posts