[알고리즘] 그리디 - 1417 1758 27446 2777 17392 11000
그리디 알고리즘
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))
'알고리즘' 카테고리의 다른 글
[알고리즘] dp - 백준 25644 1904 11060 1309 15486 (0) | 2023.03.18 |
---|---|
[알고리즘] BFS - 백준 2589 2636 5427 9205 13913 17836 (0) | 2023.03.16 |
[알고리즘] 플로이드 - 백준 11403 1389 11404 2458 1956 14938 (0) | 2023.03.15 |
[알고리즘] 다익스트라 - 백준 18352 1446 1916 5972 13549 17396 (0) | 2023.03.14 |
[알고리즘] 정렬 - 백준 1181 3273 2075 11497 2170 (0) | 2023.03.06 |