반응형

과자 나눠주기

티어 : Silver 2
시간 제한 : 1 초
메모리 제한 : 256 MB
알고리즘 분류 : 이분 탐색, 매개 변수 탐색

 

문제

명절이 되면, 홍익이 집에는 조카들이 놀러 온다. 떼를 쓰는 조카들을 달래기 위해 홍익이는 막대 과자를 하나씩 나눠준다.

조카들이 과자를 먹는 동안은 떼를 쓰지 않기 때문에, 홍익이는 조카들에게 최대한 긴 과자를 나눠주려고 한다.

그런데 나눠준 과자의 길이가 하나라도 다르면 조카끼리 싸움이 일어난다. 따라서 반드시 모든 조카에게 같은 길이의 막대 과자를 나눠주어야 한다.

M명의 조카가 있고 N개의 과자가 있을 때, 조카 1명에게 줄 수 있는 막대 과자의 최대 길이를 구하라.

단, 막대 과자는 길이와 상관없이 여러 조각으로 나눠질 수 있지만, 과자를 하나로 합칠 수는 없다. 단, 막대 과자의 길이는 양의 정수여야 한다.

 

입력

첫째 줄에 조카의 수 M (1 ≤ M ≤ 1,000,000), 과자의 수 N (1 ≤ N ≤ 1,000,000)이 주어진다.

둘째 줄에 과자 N개의 길이 L1, L2, ..., LN이 공백으로 구분되어 주어진다. 과자의 길이는 (1 ≤ L1, L2, ..., LN ≤ 1,000,000,000) 를 만족한다.

 

출력

첫째 줄에 조카 1명에게 줄 수 있는 막대 과자의 최대 길이를 출력한다.

단, 모든 조카에게 같은 길이의 막대과자를 나눠줄 수 없다면, 0을 출력한다.

 

예제 입출력

반응형

Algorithm

이진탐색
1. 과자의 길이를 오름차순 정렬
2. 중간 값을 찾아 해당 길이로 과자 만들기
3-1. 아이의 수보다 부족하면 왼쪽부분 탐색
3-2. 아이의 수보다 많으면 오른쪽 탐색

 

Code

import sys
input = sys.stdin.readline

M, N = map(int, input().split())
snack = list(map(int, input().split()))
answer = 0

# 과자의 길이를 오름차순 정렬
snack.sort()

# 이진탐색
start = 1
end = snack[-1]
while start <= end:
    # 중심값 찾기
    mid = (start+end)//2
    
    # 해당 길이로 과자 만들기
    count = 0
    for x in snack:
        if x >= mid:
            # 나눠줄 수 있는 조카의 수 = 과자를 mid 길이로 나누었을 때의 몫의 합
            count += x//mid
            
    # 과자 개수가 조카 수보다 적으면 왼쪽 부분 탐색 (더 짧은 과자 길이 찾기)
    if count < M:
        end = mid - 1
    # 과자 개수가 조카 수보다 많으면 오른쪽 부분 탐색 (더 긴 과자 길이 찾기)
    else:
        answer = mid
        start = mid + 1

print(answer)

메모리: 239748 KB
시간: 868 ms

반응형
반응형

가장 긴 바이토닉 부분 수열

티어 : Gold 3
시간 제한 : 1 초
메모리 제한 : 256 MB
알고리즘 분류 : 다이나믹 프로그래밍

 

문제

수열 S가 어떤 수 Sk를 기준으로 S1 < S2 < ... Sk-1 < Sk > Sk+1 > ... SN-1 > SN을 만족한다면, 그 수열을 바이토닉 수열이라고 한다.

예를 들어, {10, 20, 30, 25, 20}과 {10, 20, 30, 40}, {50, 40, 25, 10} 은 바이토닉 수열이지만,  {1, 2, 3, 2, 1, 2, 3, 2, 1}과 {10, 20, 30, 40, 20, 30} 은 바이토닉 수열이 아니다.

수열 A가 주어졌을 때, 그 수열의 부분 수열 중 바이토닉 수열이면서 가장 긴 수열의 길이를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 수열 A의 크기 N이 주어지고, 둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ N ≤ 1,000, 1 ≤ Ai ≤ 1,000)

 

출력

첫째 줄에 수열 A의 부분 수열 중에서 가장 긴 바이토닉 수열의 길이를 출력한다.

 

예제 입출력

반응형

Algorithm

Dynamic Programming
1. 최장 증가수열 구하기
2. 최장 감소수열 구하기
3. 최장 증가수열 + 최장 감소수열의 최댓값 - 1 출력

 

Code

import sys
input = sys.stdin.readline

N = int(input())
A = [int(num) for num in input().split()]

lis = [1] * N # 최장 증가 수열
lds = [1] * N # 최장 감소 수열

# 최장 증가수열 구하기
for i in range(1, N):
    for j in range(i):
        if A[j] < A[i]:
            lis[i] = max(lis[i], lis[j] + 1)
            
# 최장 감소수열 구하기
A.reverse()
for i in range(1, N):
    for j in range(i):
        if A[j] < A[i]:
            lds[i] = max(lds[i], lds[j] + 1)

# lis와 lds의 합의 최댓값 - 1
lds.reverse()
dp = []
for idx in range(N):
    dp.append(lis[idx] + lds[idx])
print(max(dp) - 1)

메모리: 30840 KB
시간: 344 ms

반응형
반응형

가장 큰 증가 부분 수열

티어 : Silver 2
시간 제한 : 1 초
메모리 제한 : 256 MB
알고리즘 분류 : 다이나믹 프로그래밍

 

문제

수열 A가 주어졌을 때, 그 수열의 증가 부분 수열 중에서 합이 가장 큰 것을 구하는 프로그램을 작성하시오.

예를 들어, 수열 A = {1, 100, 2, 50, 60, 3, 5, 6, 7, 8} 인 경우에 합이 가장 큰 증가 부분 수열은 A = {1, 100, 2, 50, 60, 3, 5, 6, 7, 8} 이고, 합은 113이다.

 

입력

첫째 줄에 수열 A의 크기 N (1 ≤ N ≤ 1,000)이 주어진다.

둘째 줄에는 수열 A를 이루고 있는 Ai가 주어진다. (1 ≤ Ai ≤ 1,000)

 

출력

첫째 줄에 수열 A의 합이 가장 큰 증가 부분 수열의 합을 출력한다.

 

예제 입출력

반응형

Algorithm

Dynamic Programming
점화식
: dp[i] = max(dp[i], dp[j] + A[i])

 

Code

N = int(input())
A = [int(num) for num in input().split()]

dp = A[:]
dp[0] = A[0]
for i in range(1, N):
    for j in range(i):
        if A[j] < A[i]:
            dp[i] = max(dp[i], dp[j] + A[i])

print(max(dp))

메모리: 30840 KB
시간: 208 ms

 

도움받은 게시물

https://www.acmicpc.net/board/view/67313

 

글 읽기 - 게시판에 반례 다 넣어봤는데 틀리는게없습니다.. 반례좀 찾아주시면 감사하겠습니다

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

반응형
반응형

포도주 시식

티어 : Silver 1
시간 제한 : 2 초
메모리 제한 : 128 MB
알고리즘 분류 : 다이나믹 프로그래밍

 

문제

효주는 포도주 시식회에 갔다. 그 곳에 갔더니, 테이블 위에 다양한 포도주가 들어있는 포도주 잔이 일렬로 놓여 있었다. 효주는 포도주 시식을 하려고 하는데, 여기에는 다음과 같은 두 가지 규칙이 있다.

  1. 포도주 잔을 선택하면 그 잔에 들어있는 포도주는 모두 마셔야 하고, 마신 후에는 원래 위치에 다시 놓아야 한다.
  2. 연속으로 놓여 있는 3잔을 모두 마실 수는 없다.

효주는 될 수 있는 대로 많은 양의 포도주를 맛보기 위해서 어떤 포도주 잔을 선택해야 할지 고민하고 있다. 1부터 n까지의 번호가 붙어 있는 n개의 포도주 잔이 순서대로 테이블 위에 놓여 있고, 각 포도주 잔에 들어있는 포도주의 양이 주어졌을 때, 효주를 도와 가장 많은 양의 포도주를 마실 수 있도록 하는 프로그램을 작성하시오. 

예를 들어 6개의 포도주 잔이 있고, 각각의 잔에 순서대로 6, 10, 13, 9, 8, 1 만큼의 포도주가 들어 있을 때, 첫 번째, 두 번째, 네 번째, 다섯 번째 포도주 잔을 선택하면 총 포도주 양이 33으로 최대로 마실 수 있다.

 

입력

첫째 줄에 포도주 잔의 개수 n이 주어진다. (1 ≤ n ≤ 10,000) 둘째 줄부터 n+1번째 줄까지 포도주 잔에 들어있는 포도주의 양이 순서대로 주어진다. 포도주의 양은 1,000 이하의 음이 아닌 정수이다.

 

출력

첫째 줄에 최대로 마실 수 있는 포도주의 양을 출력한다.

 

예제 입출력

반응형

Algorithm

Dynamic Programming
점화식

dp[3] = max(1 + 2, 2 + 3, 1 + 3)
dp[4] = max(1+2+4, 1+3+4, 1+2+3)
...
dp[n] = max(dp[n-3]+graph[n-1]+graph[n], dp[n-2]+graph[n], dp[n-1])

 

Code

n = int(input())
graph = [0]
for _ in range(n):
    graph.append(int(input()))

dp = [0] * (n+1)
dp[1] = graph[1]
if n > 1:
    dp[2] = graph[1] + graph[2]
if n > 2:
    dp[3] = max(dp[1] + graph[3], dp[2], graph[2] + graph[3])

for idx in range(4, n+1):
    dp[idx] = max(dp[idx-3] + graph[idx-1] + graph[idx], dp[idx-2] + graph[idx], dp[idx-1])
print(dp[-1])

메모리: 30840 KB
시간: 536 ms

 

도움받은 게시물

https://www.acmicpc.net/board/view/80678

 

글 읽기 - [java] 반례좀 찾아주실수 있나요ㅠ 질문게시판에있는거 다쳐봤습니다

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

 

반응형
반응형

스티커

티어 : Silver 1
시간 제한 : 1 초
메모리 제한 : 256 MB
알고리즘 분류 : 다이나믹 프로그래밍

 

문제

상근이의 여동생 상냥이는 문방구에서 스티커 2n개를 구매했다. 스티커는 그림 (a)와 같이 2행 n열로 배치되어 있다. 상냥이는 스티커를 이용해 책상을 꾸미려고 한다.

상냥이가 구매한 스티커의 품질은 매우 좋지 않다. 스티커 한 장을 떼면, 그 스티커와 변을 공유하는 스티커는 모두 찢어져서 사용할 수 없게 된다. 즉, 뗀 스티커의 왼쪽, 오른쪽, 위, 아래에 있는 스티커는 사용할 수 없게 된다.

모든 스티커를 붙일 수 없게된 상냥이는 각 스티커에 점수를 매기고, 점수의 합이 최대가 되게 스티커를 떼어내려고 한다. 먼저, 그림 (b)와 같이 각 스티커에 점수를 매겼다. 상냥이가 뗄 수 있는 스티커의 점수의 최댓값을 구하는 프로그램을 작성하시오. 즉, 2n개의 스티커 중에서 점수의 합이 최대가 되면서 서로 변을 공유 하지 않는 스티커 집합을 구해야 한다.

위의 그림의 경우에 점수가 50, 50, 100, 60인 스티커를 고르면, 점수는 260이 되고 이 것이 최대 점수이다. 가장 높은 점수를 가지는 두 스티커 (100과 70)은 변을 공유하기 때문에, 동시에 뗄 수 없다.

 

입력

첫째 줄에 테스트 케이스의 개수 T가 주어진다. 각 테스트 케이스의 첫째 줄에는 n (1 ≤ n ≤ 100,000)이 주어진다. 다음 두 줄에는 n개의 정수가 주어지며, 각 정수는 그 위치에 해당하는 스티커의 점수이다. 연속하는 두 정수 사이에는 빈 칸이 하나 있다. 점수는 0보다 크거나 같고, 100보다 작거나 같은 정수이다. 

 

출력

각 테스트 케이스 마다, 2n개의 스티커 중에서 두 변을 공유하지 않는 스티커 점수의 최댓값을 출력한다.

 

예제 입출력

반응형

Algorithm

Dynamic Programming
점화식

dp[i][j] = max(dp[x][y-1], dp[x+1][y-1] + graph[x][y]) (i == 0)
dp[i][j] = max(dp[x][y-1], dp[x-1][y-1] + graph[x][y]) (i == 1)

 

Code

import sys
input = sys.stdin.readline

T = int(input())
for _ in range(T):
    n = int(input())
    graph = [list(map(int, input().split())) for _ in range(2)]
    
    dp = [[0 for _ in range(n)] for _ in range(2)]
    dp[0][0] = graph[0][0]
    dp[1][0] = graph[1][0]
    for y in range(1, n):
        for x in range(2):
            # x 가 0일 때
            if x == 0:
                dp[x][y] = max(dp[x][y-1], dp[x+1][y-1] + graph[x][y])
            else:
                dp[x][y] = max(dp[x][y-1], dp[x-1][y-1] + graph[x][y])
    print(max(dp[0][-1], dp[1][-1]))

메모리: 47620 KB
시간: 1232 ms

반응형
반응형

이친수

티어 : Silver 3
시간 제한 : 2 초
메모리 제한 : 128 MB
알고리즘 분류 : 다이나믹 프로그래밍

 

문제

0과 1로만 이루어진 수를 이진수라 한다. 이러한 이진수 중 특별한 성질을 갖는 것들이 있는데, 이들을 이친수(pinary number)라 한다. 이친수는 다음의 성질을 만족한다.

  1. 이친수는 0으로 시작하지 않는다.
  2. 이친수에서는 1이 두 번 연속으로 나타나지 않는다. 즉, 11을 부분 문자열로 갖지 않는다.

예를 들면 1, 10, 100, 101, 1000, 1001 등이 이친수가 된다. 하지만 0010101이나 101101은 각각 1, 2번 규칙에 위배되므로 이친수가 아니다.

N(1 ≤ N ≤ 90)이 주어졌을 때, N자리 이친수의 개수를 구하는 프로그램을 작성하시오.

 

입력

첫째 줄에 N이 주어진다.

 

출력

첫째 줄에 N자리 이친수의 개수를 출력한다.

 

예제 입출력

반응형

Algorithm

Dynamic Programming
점화식 : dp[i] = dp[i-1] + dp[i-2]

 

Code

N = int(input())
dp = [0] * (N+1)
dp[1] = 1
if N > 1:
    dp[2] = 1
    
for idx in range(2, N+1):
    dp[idx] = dp[idx-1] + dp[idx-2]

print(dp[N])

메모리: 30840 KB
시간: 72 ms

반응형

'백준 > Python' 카테고리의 다른 글

[백준 2156] 포도주 시식 Python  (0) 2022.06.01
[백준 9465] 스티커 Python  (0) 2022.06.01
[백준 11057] 오르막 수 Python  (0) 2022.05.31
[백준 10844] 쉬운 계단 수 Python  (0) 2022.05.31
[백준 2468] 안전 영역 Python  (0) 2022.05.31
반응형

오르막 수

티어 : Silver 1
시간 제한 : 1 초
메모리 제한 : 256 MB
알고리즘 분류 : 다이나믹 프로그래밍

 

문제

오르막 수는 수의 자리가 오름차순을 이루는 수를 말한다. 이때, 인접한 수가 같아도 오름차순으로 친다.

예를 들어, 2234와 3678, 11119는 오르막 수이지만, 2232, 3676, 91111은 오르막 수가 아니다.

수의 길이 N이 주어졌을 때, 오르막 수의 개수를 구하는 프로그램을 작성하시오. 수는 0으로 시작할 수 있다.

 

입력

첫째 줄에 N (1 ≤ N ≤ 1,000)이 주어진다.

 

출력

첫째 줄에 길이가 N인 오르막 수의 개수를 10,007로 나눈 나머지를 출력한다.

 

예제 입출력

반응형

Algorithm

Dynamic Programming
점화식
dp[i][j] = dp[i][j-1] - dp[i-1][j-1] (j != 0)
dp[i][0] = sum(dp[i-1])

 

Code

N = int(input())
# dp table 초기화
dp = [[0 for _ in range(10)] for _ in range(N+1)]
dp[1] = [1] * 10

num = 0
for i in range(2, N+1):
    for j in range(10):
        if j == 0:
            dp[i][0] = sum(dp[i-1])
        else:
            dp[i][j] = dp[i][j-1] - dp[i-1][j-1]
            
print(sum(dp[N]) % 10007)

메모리: 30840 KB
시간: 76 ms

반응형

'백준 > Python' 카테고리의 다른 글

[백준 9465] 스티커 Python  (0) 2022.06.01
[백준 2193] 이친수 Python  (0) 2022.05.31
[백준 10844] 쉬운 계단 수 Python  (0) 2022.05.31
[백준 2468] 안전 영역 Python  (0) 2022.05.31
[백준 16953] A→B Python  (0) 2022.05.30
반응형

쉬운 계단 수

티어 : Silver 1
시간 제한 : 1 초
메모리 제한 : 256 MB
알고리즘 분류 : 다이나믹 프로그래밍

 

문제

45656이란 수를 보자.

이 수는 인접한 모든 자리의 차이가 1이다. 이런 수를 계단 수라고 한다.

N이 주어질 때, 길이가 N인 계단 수가 총 몇 개 있는지 구해보자. 0으로 시작하는 수는 계단수가 아니다.

 

입력

첫째 줄에 N이 주어진다. N은 1보다 크거나 같고, 100보다 작거나 같은 자연수이다.

 

출력

첫째 줄에 정답을 1,000,000,000으로 나눈 나머지를 출력한다.

 

예제 입출력

반응형

Algorithm

Dynamic Programming
i : 숫자 자릿수, j : j로 시작하는 숫자의 개수
dp[i][j] = dp[i-1][1] (j == 0)
dp[i][j] = dp[i-1][8] (j == 9)
dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1] (j != 0, j != 9)

 

Code

N = int(input())
dp = [[0 for _ in range(10)] for _ in range(N+1)]
dp[1] = [1 for _ in range(10)]

for i in range(2, N+1):
    for j in range(10):
        # j가 0이면 1로 변경
        if j == 0:
            dp[i][j] = dp[i-1][1]
        # j가 9이면 i-1의 j-1의 값과 동일
        elif j == 9:
            dp[i][j] = dp[i-1][8]
        # 그 외의 경우
        else:
            dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1]

print((sum(dp[N])-dp[N][0])%1000000000)

메모리: 30840 KB
시간: 76 ms

반응형

'백준 > Python' 카테고리의 다른 글

[백준 2193] 이친수 Python  (0) 2022.05.31
[백준 11057] 오르막 수 Python  (0) 2022.05.31
[백준 2468] 안전 영역 Python  (0) 2022.05.31
[백준 16953] A→B Python  (0) 2022.05.30
[백준 9372] 상근이의 여행 Python  (0) 2022.05.30

+ Recent posts