그리디 알고리즘

    Greedy = 탐욕

    말 그대로 각 단계에서 가장 욕심을 부려서 최선의 선택을 하는 것

    근데 이게 결과적으로 최선의 선택으로 통하는 경우 / 통하지 않는 경우가 있다.

    당연히 그리디 알고리즘은 이 탐욕법이 통하는 문제에 쓰는 것

     

    1417 국회의원 선거

     

    오랜만에 알고리즘 하니까 머리가 안돌아간다...

    A = 다솜, B, C 총 3명의 후보가 있다 치고,

    A: 5, B: 7, C: 7

    A+B+C = 19, 19/3 = 6.xxx.... 대충 반올림하면 7 이고 -5 하면 2

    이렇게 생각해봤다

    (사실 더 생각하기 귀찮았다)

    근데 후보 1명이면 어칼려고....... 당연히 틀렸다.

    그래서 다시 생각을 해봤다.

     

    A 기준 B, C 를 정렬하면 5 < 7, 7

    한명을 매수하면 6 | 6, 7

    다시 정렬하면  6  < 7, 6

    그러면 또 한명을 매수하면

    7 > 6, 6

     

    while 문으로 정렬을 계속 돌려주고,

    A보다 크면 1씩 빼준 후 A에게 더해주다가

    맨 앞 숫자가 A보다 작으면 루프 종료

     

    N = int(input())
    dasom = int(input())
    others = []
    for _ in range(1, N):
    others.append(int(input()))
    ans = 0
    if N == 1:
    ans = 0
    else:
    others.sort(reverse=True)
    while others[0] >= dasom:
    others[0] -= 1
    dasom += 1
    ans += 1
    others.sort(reverse=True)
    print(ans)

     

     

    1758 알바생 강호

    팁 = 원래 주려고 생각했던 돈 - (등수 - 1)

    손님의 수를 바꿨을 때 팁의 최댓값 구하기

     

    3원, 2원, 1원을 주고싶어함 -> 위에 문제랑 비슷한듯??

    일단 3원 받아 -> 그럼 다음에 받을 수 있는 팁은 자동으로 1이 빠진 1원 0원 -> 일단 1원 받아 -> 또 1이 빠진  => 0원 끝

     

    위 문제에서 정렬을 max 로 바꾸면 거의 비슷함

     

    N = int(input())
    tips = [0] * N
    for i in range(N):
    tips[i] = int(input())
    ans = 0
    while max(tips) > 0:
    ans += max(tips)
    tips.remove(max(tips))
    tips = [x-1 for x in tips]
    print(ans)

    근데 시간 초과 떴다ㅏㅏㅏㅏㅏㅏㅏㅏㅏ max 시간복잡도가 O(n)이라 반복문 돌면서 돌아버린거같다

     

    그래서 그냥 정렬 한번 하는걸로 결정했다

     

    N = int(input())
    tips = [0] * N
    for i in range(N):
    tips[i] = int(input())
    ans = 0
    tips.sort(reverse = True)
    loop = 1
    for i in range(len(tips)):
    if (tips[0] - (loop - 1) > 0) > 0:
    ans += tips[0] - (loop - 1)
    tips.pop(0)
    loop += 1
    print(ans)

     

     

    27446 랩실에서 잘 자요

    창조공포 가득한 문제다... 쫄려서 머리가 안돌아가더라

     

    n,m = map(int, input().split())
    pages = list(map(int, input().split()))
    pages = list(set(pages))
    pages.sort()
    ink = 0
    all_pages = [i for i in range(1, n+1)]
    to_print = set(all_pages) - set(pages)
    to_print = list(to_print)
    to_print.sort()
    pointer = 0
    while pointer <= len(to_print)-1:
    prev_pointer = pointer
    if pointer != len(to_print)-1:
    while (to_print[pointer+1] - to_print[pointer]) < 4:
    pointer += 1
    if pointer == len(to_print)-1:
    break
    ink += 5 + 2*(to_print[pointer] - to_print[prev_pointer]+1)
    pointer += 1
    print(ink)

     

    뭔가 포인터 개념이 갑자기 생각나서 한번 써봤는데 이렇게 쓰는게 아닌 것 같지만.. 우선 맞았으니 코드는 첨부한다.

    페이지 사이의 거리가 4 이상이면 따로 출력하고, 그 밑이면 한번에 출력하는 방법으로 코드를 작성했다.

     

    2777 숫자 놀이

     

    개인적으로 좀 어려웠던 문제다.

    인수를 찾아낸 후에 10 밑의 인수들로만 이루어지도록 해서 숫자를 만들어야 된다는 생각만 들어서 코드 흐름이 감이 오질 않아 다른 분들의 코드를 참고해서 풀었다. 생각해보니까 몇 자리 수인지만 구하면 되는건데 내가 너무 복잡하게 생각했다.

    t = int(input())
    numbers = [9,8,7,6,5,4,3,2]
    results = []
    for _ in range(t):
    n = int(input())
    nums = []
    tmp = n
    while True:
    cnt = 0
    if tmp == 1:
    nums.append(1)
    break # n이 1이면 1이 답이니까 그대로 break
    for s in numbers:
    if tmp%s == 0: # 2~9중 9부터 나눠본다 나눠지면 인수이므로 nums 배열에 저장
    nums.append(s)
    tmp /= s
    break
    cnt += 1
    if cnt == 8:
    if tmp >= 10: #계속 나눴는데도 10 이상이라면 빠져나와서 -1을 답으로 결정
    break
    if tmp == 1: # 완전히 나누어 떨어지니까 나
    break
    if cnt == 8:
    results.append(-1)
    else:
    results.append(len(nums))
    for i in range(len(results)):
    print(results[i])

     

     

    17392 우울한 방학

    인호는 인싸인듯 하다.

    약속이 없는 날은 어제의 기분 - 1

    인호의 약속 개수가 3, 방학일이 10일, 약속 각각의 행복이 2 2 1

    우울을 최소화하는 것이 중요하므로 우울이 퐁당퐁당이 되어야 한다

    약2 1 0 약2 1 0 약 1 0 최대 8일간 견딜 수 있으므로 우울을 그 사이에 하나씩 넣어주면 총 우울은 2가 된다.

    이 흐름대로 작성한 코드는 다음과 같다.

    n, m = map(int, input().split())
    if n == 0:
    print(m**2)
    else:
    happy = list(map(int, input().split()))
    not_gloomy = [x+1 for x in happy]
    if sum(not_gloomy) >= m:
    print(0)
    else:
    gloomy_days = m - sum(not_gloomy)
    if gloomy_days <= len(not_gloomy) + 1:
    print(gloomy_days)
    else:
    print(gloomy_days + 3*(gloomy_days - len(not_gloomy) + 1))

     

    흠 근데 틀려서 다시 짜봄

    우울 합을 잘못생각했따 20일 우울하면 400이 우울이 아니라 시그마 엑스제곱 1~20임 ㄷㄷ

    하.. 이거땜에 별짓 다하느라 코드가 좀 꼬였는데 어쨌든 알아내서 해결했으니까..

    수정한 코드는 다음과 같다.

    n, m = map(int, input().split())
    ans = 0
    if n == 0:
    print(sum(x**2 for x in range(1, m+1)))
    else:
    happy = list(map(int, input().split()))
    not_gloomy = [x+1 for x in happy]
    if sum(not_gloomy) >= m:
    print(0)
    else:
    gloomy_days = m - sum(not_gloomy)
    if gloomy_days <= len(not_gloomy) + 1:
    print(gloomy_days)
    else:
    blanks = len(not_gloomy) + 1
    blank_list = [gloomy_days // blanks] * blanks
    tmp = gloomy_days % blanks
    while tmp > 0:
    for i in range(len(blank_list)):
    if tmp == 0:
    break
    tmp -= 1
    blank_list[i] += 1
    for x in blank_list:
    for i in range(1, x+1):
    ans += i**2
    print(ans)

     

    11000 강의실 배정

     

     

    최대한 숫자가 이어지게 짜면 된다

    import sys
    input = sys.stdin.readline
    n = int(input())
    classes = [[]]*n
    ans = n
    for i in range(n):
    classes[i] = list(map(int, input().split()))
    classes.sort(key = lambda x: (x[1], x[0])) #끝나는 시간이 이르고, 이후 시작 시간이 이른 순으로 정렬
    for i in range(len(classes)):
    end_time = classes[i][1]
    for j in range(i+1, len(classes)):
    start_time = classes[j][0]
    if end_time > start_time:
    continue
    else:
    ans -= 1
    print(ans)

     

    시간초과가 뜰 거 같았는데 역시였다

    힙큐 잘 못해서 안썼는데 써야겠다는 생각이 정말 강하게 들어서 코드를 새로 수정했다.

    import sys
    import heapq
    input = sys.stdin.readline
    n = int(input())
    classes = []
    number = []
    for _ in range(n):
    classes.append(list(map(int, input().split())))
    classes.sort()
    heapq.heappush(number, classes[0][1]) #힙(넘버)에 끝나는시간을 넣어
    for i in range(1, n):
    if classes[i][0] < number[0]: # 만약에 클래스의 시작시간이 끝나는시간보다 작아
    heapq.heappush(number, classes[i][1]) # 넘버 힙에 끝나는 시간도 넣어
    else: # 만약에 클래스 시작시간이 현재 들어있는 끝나는 시간보다 커
    heapq.heappop(number) # 힙에서 빼
    heapq.heappush(number, classes[i][1]) # 그리고 다음걸 넣어
    print(len(number))
    힙큐를 좀더 잘 써보면 코드 짜기가 쉬워질 것 같다.

    Posted by 저본