728x90

백준 CPP 공부 2025.05.16
1181번 단어 정렬

1. 문제
알파벳 소문자로 이루어진 N개의 단어가 들어오면 
아래와 같은 조건에 따라 정렬하는 프로그램을 작성하시오.

1) 길이가 짧은 것부터
2) 길이가 같으면 사전 순으로

단, 중복된 단어는 하나만 남기고 제거해야 한다.

3. 입력
첫째 줄에 단어의 개수 N이 주어진다. (1 ≤ N ≤ 20,000) 
둘째 줄부터 N개의 줄에 걸쳐 알파벳 소문자로 이루어진 단어가 한 줄에 하나씩 주어진다. 
주어지는 문자열의 길이는 50을 넘지 않는다.

3. 출력
조건에 따라 정렬하여 단어들을 출력한다.

4. 문제 풀이

#include <iostream>
#include <list>
#include <string>
using namespace std;

// 문자 비교 기준 함수 작성
bool wordcompare(string A, string B){
if (A.length() == B.length()) {
return A < B;
}
else {
return A.length() < B.length();
}
}

int main(){
    int n;
    cin >> n;
    
    list<string> word;
    for (int i = 0; i<n; i++){
        string str;
        cin >> str;
        word.push_back(str);
    }
    
    word.sort(wordcompare); // 문자 wordcompare에 맞게 정렬
    word.unique(); // 문자 중복 제거
    
    for (auto it = word.begin(); it != word.end(); it++){
        cout << *it << endl;
    }
    
    return 0;
}



5. 문제 링크
https://www.acmicpc.net/problem/1181

728x90
728x90

백준 파이썬 공부 2025.04.05
6064번 카잉 달력 (실버 1)

1. 문제
최근에 ICPC 탐사대는 남아메리카의 잉카 제국이 놀라운 문명을 지닌 카잉 제국을 토대로 하여 세워졌다는 사실을 발견했다. 
카잉 제국의 백성들은 특이한 달력을 사용한 것으로 알려져 있다. 

그들은 M과 N보다 작거나 같은 두 개의 자연수 x, y를 가지고 각 년도를 <x:y>와 같은 형식으로 표현하였다. 
그들은 이 세상의 시초에 해당하는 첫 번째 해를 <1:1>로 표현하고, 두 번째 해를 <2:2>로 표현하였다. 

<x:y>의 다음 해를 표현한 것을 <x':y'>이라고 하자. 
만일 x < M 이면 x' = x + 1이고, 그렇지 않으면 x' = 1이다. 
같은 방식으로 만일 y < N이면 y' = y + 1이고, 그렇지 않으면 y' = 1이다. 
<M:N>은 그들 달력의 마지막 해로서, 이 해에 세상의 종말이 도래한다는 예언이 전해 온다.

예를 들어, M = 10 이고 N = 12라고 하자. 
첫 번째 해는 <1:1>로 표현되고, 11번째 해는 <1:11>로 표현된다. 
<3:1>은 13번째 해를 나타내고, <10:12>는 마지막인 60번째 해를 나타낸다.

네 개의 정수 M, N, x와 y가 주어질 때, <M:N>이 카잉 달력의 마지막 해라고 하면 
<x:y>는 몇 번째 해를 나타내는지 구하는 프로그램을 작성하라.

2. 입력
입력 데이터는 표준 입력을 사용한다. 

입력은 T개의 테스트 데이터로 구성된다. 
입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 

각 테스트 데이터는 한 줄로 구성된다. 
각 줄에는 네 개의 정수 M, N, x와 y가 주어진다. 
(1 ≤ M, N ≤ 40,000, 1 ≤ x ≤ M, 1 ≤ y ≤ N) 
여기서 <M:N>은 카잉 달력의 마지막 해를 나타낸다.

3. 출력
출력은 표준 출력을 사용한다. 
각 테스트 데이터에 대해, 정수 k를 한 줄에 출력한다. 
여기서 k는 <x:y>가 k번째 해를 나타내는 것을 의미한다. 
만일 <x:y>에 의해 표현되는 해가 없다면, 즉, <x:y>가 유효하지 않은 표현이면, -1을 출력한다.

4. 문제 해설
이건 정수론에 대해 어느 정도 알아야 풀이가 가능한 문제이다.
단순히 <1:1> 에서 부터 브루트 포스로 계산하려고 할 시에는 시간초과 엔딩이 난다.

<x:y> 일때, 이는 <(해당 해) % M : (해당 해) % N> 으로 나타낼 수 있다.
그 말을 식으로 작성하면,
answer = M * A1(나눗셈의 몫1) + x = N * A2(나눗셈의 몫2) + y
answer - x = M * A1 >> (answer - x) % M == 0
answer - y = N * A2 >> (answer - y) % N == 0
이걸 이용해보자

일단 가능한 마지막 해는 M과 N의 최소 공배수이고,
이 값을 넘어가면 해당 x, y에 해당하는 해는 존재하지 않는다고 보면 된다.
즉 -1

그리고 초기값을 x로 설정해 놓고 M을 더해가며,
각 값 - y가 N으로 나누어 떨어지는지 검사를 해가면 된다.

>> 코드

import sys

# 멸망의 해(마지막 해)를 구하기 위한 최대공약수와 최소공배수 함수
# 최대 공약수 함수
def gcd(x, y):
    if y == 0:
        return x
    else:
        return gcd(y, x%y)

# 최소 공배수 함수
def lcm(x, y):
    return x * y / gcd(x, y)

# 계산 함수
def calculate(M, N, x, y):
    # 초기 시작 값 x로 시작
    answer = x
    # 마지막 해 M, N의 최소 공배수로 설정
    max_value = lcm(M, N)
    # 해당값 - y가 N으로 나누어 떨어질 때까지 M 더하기
    while answer <= max_value:
        if (answer - y) % N == 0:
            return answer
        answer += M
    return -1

T = int(sys.stdin.readline().strip())
for _ in range(T):
    M, N, x, y = map(int, sys.stdin.readline().strip().split())
    
    print(calculate(M, N, x, y))


5. 문제 링크
https://www.acmicpc.net/problem/6064

728x90
728x90

백준 파이썬 공부 2025.04.02
30804번 과일 탕후루 (실버 2)

1. 문제
은하는 긴 막대에 N개의 과일이 꽂혀있는 과일 탕후루를 만들었습니다. 
과일의 각 종류에는 1부터 9까지의 번호가 붙어있고, 
앞쪽부터 차례로 S_1, S_2, ..., S_N번 과일이 꽂혀있습니다. 
과일 탕후루를 다 만든 은하가 주문을 다시 확인해보니 
과일을 두 종류 이하로 사용해달라는 요청이 있었습니다.

탕후루를 다시 만들 시간이 없었던 은하는, 
막대의 앞쪽과 뒤쪽에서 몇 개의 과일을 빼서 두 종류 이하의 과일만 남기기로 했습니다. 
앞에서 a개, 뒤에서 b개의 과일을 빼면 S_{a+1}, S_{a+2}, ..., S_{N-b-1}, S_{N-b}번 과일, 
총 N-(a+b)개가 꽂혀있는 탕후루가 됩니다. (0 <= a, b, a+b < N) 

이렇게 만들 수 있는 과일을 두 종류 이하로 사용한 탕후루 중에서, 
과일의 개수가 가장 많은 탕후루의 과일 개수를 구하세요.

2. 입력
첫 줄에 과일의 개수 N이 주어집니다. (1 <= N <= 200,000) 
둘째 줄에 탕후루에 꽂힌 과일을 의미하는 N개의 정수 S_1, ..., S_N이 공백으로 구분되어 주어집니다. (1 <= S_i <= 9)

3. 출력
문제의 방법대로 만들 수 있는 과일을 두 종류 이하로 사용한 탕후루 중에서, 
과일의 개수가 가장 많은 탕후루의 과일 개수를 첫째 줄에 출력하세요.

4. 문제 풀이
투 포인터로 포인터 두개를 이동해가면서
두 포인터 사이의 과일 갯수를 확인하면서 최대의 길이를 검사하면 된다.

>>>코드

import sys

n = int(sys.stdin.readline().strip())
Tanghulu = list(map(int, sys.stdin.readline().strip().split()))

p1, p2 = 0, 0
length = 0
cnt = {}

while p2 < n:
    # p2 위치의 과일 갯수와 종류 갱신
    if Tanghulu[p2] in cnt:
        cnt[Tanghulu[p2]] += 1
    else:
        cnt[Tanghulu[p2]] = 1
    
    # cnt 의 길이 (과일의 종류)가 2개가 넘어가면 과일의 종류가 2개가 될 때까지
    while len(cnt) > 2:
        # p1 위치의 과일을 제거하면서
        cnt[Tanghulu[p1]] -= 1
        if cnt[Tanghulu[p1]] == 0:
            del cnt[Tanghulu[p1]]
        # p1을 이동
        p1 += 1
    # 최대 길이 갱신
    length = max(length, p2 - p1 + 1)
    p2 += 1
            
print(length)


5. 문제 링크
https://www.acmicpc.net/problem/30804

728x90
728x90

백준 파이썬 공부 2025.03.31
2805번 나무 자르기 (실버 2)

1. 문제
상근이는 나무 M미터가 필요하다. 
근처에 나무를 구입할 곳이 모두 망해버렸기 때문에, 정부에 벌목 허가를 요청했다. 
정부는 상근이네 집 근처의 나무 한 줄에 대한 벌목 허가를 내주었고, 
상근이는 새로 구입한 목재절단기를 이용해서 나무를 구할것이다.

목재절단기는 다음과 같이 동작한다. 
먼저, 상근이는 절단기에 높이 H를 지정해야 한다. 
높이를 지정하면 톱날이 땅으로부터 H미터 위로 올라간다. 
그 다음, 한 줄에 연속해있는 나무를 모두 절단해버린다. 
따라서, 높이가 H보다 큰 나무는 H 위의 부분이 잘릴 것이고, 낮은 나무는 잘리지 않을 것이다.
 
예를 들어, 한 줄에 연속해있는 나무의 높이가 20, 15, 10, 17이라고 하자. 
상근이가 높이를 15로 지정했다면, 나무를 자른 뒤의 높이는 15, 15, 10, 15가 될 것이고, 
상근이는 길이가 5인 나무와 2인 나무를 들고 집에 갈 것이다. (총 7미터를 집에 들고 간다) 
절단기에 설정할 수 있는 높이는 양의 정수 또는 0이다.

상근이는 환경에 매우 관심이 많기 때문에, 나무를 필요한 만큼만 집으로 가져가려고 한다. 
이때, 적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 구하는 프로그램을 작성하시오.

2. 입력
첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. 
(1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000)

둘째 줄에는 나무의 높이가 주어진다. 
나무의 높이의 합은 항상 M보다 크거나 같기 때문에, 
상근이는 집에 필요한 나무를 항상 가져갈 수 있다. 
높이는 1,000,000,000보다 작거나 같은 양의 정수 또는 0이다.

3. 출력
적어도 M미터의 나무를 집에 가져가기 위해서 절단기에 설정할 수 있는 높이의 최댓값을 출력한다.

4. 문제 풀이
전형적인 이분탐색 문제로서
start를 0 end를 max(tree) 즉 나무 중 가장 높이가 큰 나무 길이로 해놓고,
높이를 이분탐색 해가면서 자를 나무의 높이를 찾아가는 방식으로 실시한다.
다만, 필요한 나무의 길이인 m이 딱 나오지 않을 경우도 있기 때문에
필요한 나무의 길이보다 자른 총 나무의 길이가 길 때, 
자를 나무의 길이를 매번 저장해 놓으면서 갱신하는 방식을 필요로 한다.

>>> 코드

import sys

n, m = map(int, sys.stdin.readline().strip().split())
tree = list(map(int, sys.stdin.readline().strip().split()))

start = 0
end = max(tree)
while start <= end:
    mid = (end + start) // 2
    
    length = 0
    for i in range(n):
        if tree[i] > mid:
            length += tree[i] - mid
    if length >= m:
        result = mid
        start = mid + 1
    else:
        end = mid - 1

print(result)



5. 문제 링크
https://www.acmicpc.net/problem/2805

728x90
728x90

백준 파이썬 공부 2025.03.21
7662번 이중 우선순위 큐 (골드 4)

1. 문제
이중 우선순위 큐(dual priority queue)는 전형적인 우선순위 큐처럼 
데이터를 삽입, 삭제할 수 있는 자료 구조이다. 
전형적인 큐와의 차이점은 데이터를 삭제할 때 연산(operation) 명령에 따라 
우선순위가 가장 높은 데이터 또는 가장 낮은 데이터 중 하나를 삭제하는 점이다. 

이중 우선순위 큐를 위해선 두 가지 연산이 사용되는데, 
하나는 데이터를 삽입하는 연산이고 다른 하나는 데이터를 삭제하는 연산이다. 

데이터를 삭제하는 연산은 또 두 가지로 구분되는데 
하나는 우선순위가 가장 높은 것을 삭제하기 위한 것이고 
다른 하나는 우선순위가 가장 낮은 것을 삭제하기 위한 것이다.

정수만 저장하는 이중 우선순위 큐 Q가 있다고 가정하자. 
Q에 저장된 각 정수의 값 자체를 우선순위라고 간주하자.

Q에 적용될 일련의 연산이 주어질 때 이를 처리한 후 
최종적으로 Q에 저장된 데이터 중 최댓값과 최솟값을 출력하는 프로그램을 작성하라.

2. 입력
입력 데이터는 표준입력을 사용한다. 
입력은 T개의 테스트 데이터로 구성된다. 

입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 
각 테스트 데이터의 첫째 줄에는 
Q에 적용할 연산의 개수를 나타내는 정수 k (k ≤ 1,000,000)가 주어진다. 

이어지는 k 줄 각각엔 연산을 나타내는 문자(‘D’ 또는 ‘I’)와 정수 n이 주어진다. 

‘I n’은 정수 n을 Q에 삽입하는 연산을 의미한다. 
동일한 정수가 삽입될 수 있음을 참고하기 바란다. 

‘D 1’는 Q에서 최댓값을 삭제하는 연산을 의미하며, 
‘D -1’는 Q 에서 최솟값을 삭제하는 연산을 의미한다. 
최댓값(최솟값)을 삭제하는 연산에서 최댓값(최솟값)이 둘 이상인 경우, 
하나만 삭제됨을 유념하기 바란다.

만약 Q가 비어있는데 적용할 연산이 ‘D’라면 이 연산은 무시해도 좋다. 
Q에 저장될 모든 정수는 -2^31 이상 2^31 미만인 정수이다.

3. 출력
출력은 표준출력을 사용한다. 
각 테스트 데이터에 대해, 모든 연산을 처리한 후 
Q에 남아 있는 값 중 최댓값과 최솟값을 출력하라. 
두 값은 한 줄에 출력하되 하나의 공백으로 구분하라. 
만약 Q가 비어있다면 ‘EMPTY’를 출력하라.

4. 문제 풀이
일단 매번 추가하고 정렬하는 방식으로 시도한 후,
pop으로 맨 앞과 맨 뒤를 제거하는 방식으로 시도했다.
당연히 시간초과가 나온다.

>>>코드1. 정렬, 시간초과

import sys

T = int(sys.stdin.readline().strip())
for _ in range(T):
    Q = int(sys.stdin.readline().strip())
    queue = []
    for i in range(Q):
        arr = sys.stdin.readline().strip().split()
        if arr[0] ==  'I':
            queue.append(int(arr[1]))
            queue.sort()
        elif queue:
            if arr[1] == '1':
                queue.pop()
            else:
                queue.pop(0)
        
    if queue:
        if len(queue) == 1:
            num = queue.pop()
            print(num, num)
        else:
            print(queue.pop(), queue.pop(0))
    else:
        print("EMPTY")



그렇다면 제거하는 당시에 최대값과 최소값을 찾는건 어떨까?
역시나 시간초과이다.

>>>코드2. 최대값 최소값 찾기. 시간초과

import sys

T = int(sys.stdin.readline().strip())
for _ in range(T):
    Q = int(sys.stdin.readline().strip())
    queue = []
    for i in range(Q):
        arr = sys.stdin.readline().strip().split()
        if arr[0] ==  'I':
            queue.append(int(arr[1]))
        elif queue:
            if arr[1] == '1':
                queue.remove(max(queue))
            else:
                queue.remove(min(queue))
        
    if queue:
        if len(queue) == 1:
            num = queue.pop()
            print(num, num)
        else:
            print(queue.pop(), queue.pop(0))
    else:
        print("EMPTY")



>>>코드3. 그렇다면 최대값과 최소값을 저장해놓는건? 시간초과

import sys

T = int(sys.stdin.readline().strip())
for _ in range(T):
    Q = int(sys.stdin.readline().strip())
    queue = []
    Max, Min = -2**31, 2**31
    for i in range(Q):
        arr = sys.stdin.readline().strip().split()
        if arr[0] ==  'I':
            m = int(arr[1])
            queue.append(m)
            Max = max(Max, m)
            Min = min(Min, m)
        elif queue:
            if arr[1] == '1':
                queue.remove(Max)
                Max = max(queue)
            else:
                queue.remove(Min)
                Min = min(queue)
        
    if queue:
        if len(queue) == 1:
            num = queue.pop()
            print(num, num)
        else:
            print(queue.pop(), queue.pop(0))
    else:
        print("EMPTY")



저장하는 구조를 새로 생각을 해봐야겠다

최대 힙과 최소 힙에 동시에 저장을 한 후
딕셔너리로 해당 숫자와 숫자의 개수를 저장해놓는다.
삭제 시에는 해당 숫자의 개수가 0이 되면 딕셔너리에서 삭제하며,
삭제 하는 과정에서, 최대 힙과 최소 힙의 목록을 일치 시켜주는 작업을 시행한다.

큰 틀은 맞았으나, Key Error가 자꾸 발생한다.
원인은 딕셔너리 내부를 탐색하는 경우, 해당 key가 존재하지 않는 경우 오류가 난다.
따라서 해당 Key 값이 존재하지 않아도 오류가 발생하지 않는 탐색함수인
.get 함수를 사용하여 개수를 탐색한다.

get() 메서드는 다음과 같은 동작을 수행합니다:

- 만약 주어진 키(key)가 딕셔너리에 존재한다면, 해당 키에 대한 값을 반환합니다.
- 만약 주어진 키(key)가 딕셔너리에 존재하지 않는다면, 기본값(default value)을 반환합니다.
- 만약 기본값이 지정되지 않았다면, None을 반환합니다.

>>>코드 정답

import sys
import heapq

T = int(sys.stdin.readline().strip())
for _ in range(T):
    Q = int(sys.stdin.readline().strip())
    max_heap = []
    min_heap = []
    
    # 입력된 값과 개수를 저장할 딕셔너리
    cnt = {}
    for i in range(Q):
        arr = sys.stdin.readline().strip().split()
        
        # 값을 추가하는 경우
        if arr[0] ==  'I':
            n = int(arr[1])
            # 값과 개수을 딕셔너리에 저장
            if n in cnt:
                cnt[n] += 1
            else:
                cnt[n] = 1
            # 최대힙과 최소힙에 저장 (우선순위 존재)
            heapq.heappush(min_heap, n)
            heapq.heappush(max_heap, -n)
        
        # 값을 삭제하는 경우
        elif arr[0] == 'D' and cnt:
            # 최대값을 삭제하는 경우
            if arr[1] == '1':
                # 해당 값의 개수가 0 이하인 경우
                while max_heap:
                    # 최대 힙에서 삭제 (최소 힙과 목록 일치 시켜주는 작업)
                    max_val = -max_heap[0]
                    if cnt.get(max_val, 0) > 0:
                        break
                    heapq.heappop(max_heap)
                if max_heap:
                    # 해당 값의 개수 -1
                    max_val = -heapq.heappop(max_heap)
                    cnt[max_val] -= 1
                    if cnt[max_val] == 0:
                        del cnt[max_val]
            # 최소값을 삭제하는 경우
            elif arr[1] == '-1':
                # 해당 값의 개수가 0 이하인 경우
                while min_heap:
                    # 최소 힙에서 삭제 (최대 힙과 목록 일치 시켜주는 작업)
                    min_val = min_heap[0]
                    if cnt.get(min_val, 0) > 0:
                        break
                    heapq.heappop(min_heap)
                if min_heap:
                    # 해당 값의 개수 -1
                    min_val = heapq.heappop(min_heap)
                    cnt[min_val] -= 1
                    if cnt[min_val] == 0:
                        del cnt[min_val]

    if not cnt:
        print("EMPTY")
    else:
        while max_heap:
            max_val = -max_heap[0]
            if cnt.get(max_val, 0) > 0:
                break
            heapq.heappop(max_heap)
        while min_heap:
            min_val = min_heap[0]
            if cnt.get(min_val, 0) > 0:
                break
            heapq.heappop(min_heap)
        print(-max_heap[0], min_heap[0])



빡셌다.
구조는 맞는거 같은데 자꾸 오류가 발생해서 어지러웠다.

5. 문제 링크
https://www.acmicpc.net/problem/7662

728x90
728x90

백준 파이썬 공부 2025.03.17
5430번 AC (골드 5)

1. 문제
선영이는 주말에 할 일이 없어서 새로운 언어 AC를 만들었다. 
AC는 정수 배열에 연산을 하기 위해 만든 언어이다. 
이 언어에는 두 가지 함수 R(뒤집기)과 D(버리기)가 있다.

함수 R은 배열에 있는 수의 순서를 뒤집는 함수이고, D는 첫 번째 수를 버리는 함수이다. 
배열이 비어있는데 D를 사용한 경우에는 에러가 발생한다.

함수는 조합해서 한 번에 사용할 수 있다. 
예를 들어, "AB"는 A를 수행한 다음에 바로 이어서 B를 수행하는 함수이다. 
예를 들어, "RDD"는 배열을 뒤집은 다음 처음 두 수를 버리는 함수이다.

배열의 초기값과 수행할 함수가 주어졌을 때, 최종 결과를 구하는 프로그램을 작성하시오.

2. 입력
첫째 줄에 테스트 케이스의 개수 T가 주어진다. T는 최대 100이다.
각 테스트 케이스의 첫째 줄에는 수행할 함수 p가 주어진다. 
p의 길이는 1보다 크거나 같고, 100,000보다 작거나 같다.

다음 줄에는 배열에 들어있는 수의 개수 n이 주어진다. (0 ≤ n ≤ 100,000)

다음 줄에는 [x1,...,xn]과 같은 형태로 배열에 들어있는 정수가 주어진다. (1 ≤ xi ≤ 100)

전체 테스트 케이스에 주어지는 p의 길이의 합과 n의 합은 70만을 넘지 않는다.

3. 출력
각 테스트 케이스에 대해서, 입력으로 주어진 정수 배열에 함수를 수행한 결과를 출력한다. 
만약, 에러가 발생한 경우에는 error를 출력한다.

4. 문제 해설
그냥 파이썬에서 제공해주는 
deque 라이브러리의 reverse와 popleft를 이용하여 코드를 작성했다.
그러나 시간초과 엔딩..

>>>코드1. 시간초과

from collections import deque
import sys

def AC(calculation):
    for RD in calculation:
        if RD == 'R':
            num.reverse()
        elif RD == 'D':
            if num:
                num.popleft()
            else:
                print("error")
                return
    print(list(num))

T = int(sys.stdin.readline().strip())
for _ in range(T):
    calculation = sys.stdin.readline().strip()
    n = int(sys.stdin.readline().strip())
    arr = sys.stdin.readline().strip()
    
    if arr == "[]":
        num = deque()
    else:
        num = deque(map(int, arr.strip("[]").split(',')))
    AC(calculation)



보기에 reverse가 시간이 많이 들기 때문에 
reverse 가 홀수번 선언되면 pop
reverse 가 짝수번 선언되면 popleft를 시행한다.

>>>코드 2.

from collections import deque
import sys

def AC(calculation):
    flag = 0
    for RD in calculation:
        if RD == 'R':
            if flag:
                flag = 0
            else:
                flag = 1
        elif RD == 'D':
            if num:
                if flag:
                    num.pop()
                else:
                    num.popleft()
            else:
                print("error")
                return
    if num:
        if flag:
            num.reverse()
        print("[" + ",".join(num) + "]")
    else:
        print("[]")
    
T = int(sys.stdin.readline().strip())
for _ in range(T):
    calculation = sys.stdin.readline().strip()
    n = int(sys.stdin.readline().strip())
    arr = sys.stdin.readline().strip()
    
    if arr == "[]":
        num = deque()
    else:
        num = deque(arr.strip('[]').split(','))
    AC(calculation)


어우 씨
분명 구조는 맞는데 계속 헤맸다.
일단 덱을 숫자로 저장 한 후 그냥 리스트 출력을 했을 시, 틀렸습니다로 나오는데,
이는 리스트 출력시 ',' 쉼표 뒤에 공백이 존재하기 때문에 틀린 것으로 나온다.

그래서 덱을 숫자로 저장한 후 join으로 출력을 했을경우, Type error가 나온다.
이는 덱을 숫자로 저장했기 때문이라, 덱을 문자열 배열로 저장하도록하면 맞게 된다.

5. 문제 링크
https://www.acmicpc.net/problem/5430

728x90
728x90

백준 파이썬 공부 2025.03.14
17626번 Four Squares (실버 3)

1. 문제
라그랑주는 1770년에 모든 자연수는 넷 혹은 그 이하의 제곱수의 합으로 표현할 수 있다고 증명하였다. 
어떤 자연수는 복수의 방법으로 표현된다. 예를 들면, 26은 5^2과 1^2의 합이다; 
또한 4^2 + 3^2 + 1^2으로 표현할 수도 있다. 
역사적으로 암산의 명수들에게 공통적으로 주어지는 문제가 바로 자연수를 넷 혹은 그 이하의 제곱수 합으로 나타내라는 것이었다. 
1900년대 초반에 한 암산가가 15663 = 125^2 + 6^2 + 1^2 + 1^2라는 해를 구하는데 8초가 걸렸다는 보고가 있다. 
좀 더 어려운 문제에 대해서는 56초가 걸렸다: 11339 = 105^2 + 15^2 + 8^2 + 5^2.

자연수 n이 주어질 때, n을 최소 개수의 제곱수 합으로 표현하는 컴퓨터 프로그램을 작성하시오.

2. 입력
입력은 표준입력을 사용한다. 
입력은 자연수 n을 포함하는 한 줄로 구성된다. 
여기서, 1 ≤ n ≤ 50,000이다.

3. 출력
출력은 표준출력을 사용한다. 
합이 n과 같게 되는 제곱수들의 최소 개수를 한 줄에 출력한다.

4. 문제 풀이
일단 1 에서부터 차례대로 제곱수의 개수를 나열해보았다.

1 > 1
2 > 1 1
3 > 1 1 1
4 > 2
5 > 2 1
6 > 2 1 1
7 > 2 1 1 1
8 > 2 2
9 > 3
10 > 3 1
11 > 3 1 1
12 > 2 2 2
13 > 3 2
14 > 3 2 1
15 > 3 2 1 1
16 > 4
...

1 2 3 
1 2 3 4 2 
1 2 3 3 2 3 4
1

단순히 숫자들의 나열로는 규칙을 찾기 어려운것 같다
구조를 해석해보자. 제곱수의 개수를 구하고 싶은 수 n이 있을때,

해당 수 n을 넘지않는 제곱수 m 의 제곱수 개수 1 
+ n-m의 제곱수 개수

를 n보다 작은 제곱수들 중 가장 작은 제곱수 개수를 출력하면 된다.
제곱수가 굉장히 커지기 때문에,
전부 다 돌아가면서 개수를 확인할 수 있는듯하다. 
그중 가장 작은 수가 최소 제곱수의 개수 이다.

>>>코드

n = int(input())
dp = [0, 1]
for num in range(2, n+1):
    square = 1
    cnt = 4
    while square**2 <= num:
        cnt = min(cnt, dp[num-square**2] + 1)
        square += 1
    dp.append(cnt)
print(dp[n])



5. 문제 링크
https://www.acmicpc.net/problem/17626

728x90
728x90

백준 파이썬 공부 2025.03.08
11286번 절댓값 힙 (실버 1)

1. 문제
절댓값 힙은 다음과 같은 연산을 지원하는 자료구조이다.

1) 배열에 정수 x (x ≠ 0)를 넣는다.
2) 배열에서 절댓값이 가장 작은 값을 출력하고, 그 값을 배열에서 제거한다. 
절댓값이 가장 작은 값이 여러개일 때는, 가장 작은 수를 출력하고, 그 값을 배열에서 제거한다.

프로그램은 처음에 비어있는 배열에서 시작하게 된다.

2. 입력
첫째 줄에 연산의 개수 N(1≤N≤100,000)이 주어진다. 
다음 N개의 줄에는 연산에 대한 정보를 나타내는 정수 x가 주어진다. 
만약 x가 0이 아니라면 배열에 x라는 값을 넣는(추가하는) 연산이고, 
x가 0이라면 배열에서 절댓값이 가장 작은 값을 출력하고 그 값을 배열에서 제거하는 경우이다. 

입력되는 정수는 -2^(31)보다 크고, 2^(31)보다 작다.

3. 출력
입력에서 0이 주어진 회수만큼 답을 출력한다. 
만약 배열이 비어 있는 경우인데 절댓값이 가장 작은 값을 출력하라고 한 경우에는 
0을 출력하면 된다.

4. 문제 풀이
해당 문제는 전체적으로는 최소 힙 구조를 띄고 있지만,
정렬은 해당 값의 절대값을 기준으로 한다.
따라서 (절대값, 원래값) 튜플 형식으로 묶어 절대값 기준으로 저장하고, 
추출은 원래값을 내보내면 된다.

>>>코드1. heapq 라이브러리 사용

import heapq

heap = []
for _ in range(int(input())):
    n = int(input())
    if n == 0:
        if len(heap) == 0:
            print(0)
        else:
            a, b = heapq.heappop(heap)
            print(b)
    else:
        heapq.heappush(heap, (abs(n), n))




5. 문제 링크
https://www.acmicpc.net/problem/11286

728x90

+ Recent posts