일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 인공지능
- 신경망 학습
- BOJ
- 스트림암호
- 신경망
- 소프트맥스함수
- c언어
- 백준
- 활성화함수파이썬
- 항등함수
- 신경망구현
- 파이썬신경망
- 8086CPU레지스터
- 딥러닝파이썬
- C언어알고리즘
- 밑바닥부터시작하는딥러닝
- 파이썬
- C알고리즘
- 딥러닝
- C언어 알고리즘
- 머신러닝
- 달고나bof
- FTZlevel10
- 신경망파이썬
- 알고리즘
- 보안
- 백준알고리즘
- 정보보안
- 버퍼오버플로우
- BOF
- Today
- Total
HeeJ's
[01] 그리디 (greedy) 알고리즘 본문
그리디 알고리즘이란 글로벌 최적을 찾기 위해 각 단계에서 로컬 최적의 선택을 하는 문제 해결 알고리즘이다.
즉, 바로 눈 앞의 이익만을 좇는 알고리즘이다.
대부분의 경우에는 뛰어난 결과를 도출하지 못하지만, 드물게 최적해를 보장하는 경우도 있다.
어떠한 문제가 있을 때, 단순 무식하게 지금 당장 좋은 것을 고리는 방법이다.
매 순간 가장 좋아 보이는 것을 선택하며, 현재의 선택이 나중에 미칠 영향에 대해서는 고려하지 않는다.
* 탐욕 선택 속성 : 앞의 선택이 이후 선택에 영향을 주지 않는 것
그리디 알고리즘의 대표 문제들
1. 거스름돈 문제
당신은 음식점의 계산을 도와주는 점원이다.
카운터에는 거스름 돈으로 사용할 500원, 100원, 50원, 10원짜리 동전이 무한히 존재한다.
손님에게 거슬러줘야 할 돈이 N원이라면,
거슬러 줘야 하는 동전의 최소 개수는?
(단, N은 항상 10의 배수이다.)
이 문제에 접근하는 방법은 '가장 큰 화폐 단위부터' 돈을 거슬러주기 이다.
즉, 500원, 100원, 50원, 10원의 순서대로 거슬러 최소의 동전 개수로 계산하는 것이다.
이러한 방식으로 문제를 해결해보면, 만약 n이 1260원일 경우,
# n이 1620일 경우
n = 1260
count = 0
# 큰 단위의 화폐부터 차례대로 확인
coin_types = [500, 100, 50, 10]
for coin in coin_types:
count += n // coin #해당 화폐로 거슬러줄 수 있는 동전의 개수 세기
n %= coin
print(count)
그리디 알고리즘의 정당성
그리디 알고리즘은 모든 알고리즘 문제에 적용할 수 없다.
하지만 특정한 문제에 접근했을 때 정확한 답을 찾을 수 있을 때 매우 효과적이고, 직관적이다.
그리디 알고리즘으로 정답을 찾은 경우, 해법이 정당한지 검토하는 과정이 중요하다.
예로, 거스름돈 문제에서 해법이 정당한지 쉽게 검토하는 방법은
가지고 있는 동전 중에서 큰 단위가 항상 작은 단위의 배수라, 다른 해가 나올 수 없기 때문이다.
만약 문제를 처음 만나게 된다면, 차근차근 작은 수 부터 생각하면서, 방법을 거슬러 올라가서 생각하는 방식이 필요하다.
즉, 대부분의 그리디 알고리즘 문제에서는 문제 풀이를 위한 최소한의 아이디어를 떠올리고, 이것이 정당한지 검토할 수 있어야 답을 도출할 수 있다.
2. 큰 수의 법칙
다양한 수로 이루어진 배열이 있을 때 주어진 수들을 M번 더하여 가장 큰 수를 만드는 법칙이다.
단, 특정한 인덱스에 해당하는 수가 연속해서 K번을 초과하여 더해질 수 없다.
만약, [2, 4, 5, 4, 6]으로 이루어진 배열에서,
M이 8이고, K가 3일 때, 특정한 인덱스가 연속해서 세 번까지 더해질 수 있으므로,
6 + 6 + 6 + 5 + 6 + 6 + 6 + 5 = 46이 된다.
만약 [3, 4, 3, 4, 3]으로 이루어진 배열에서,
같은 수이지만 인덱스가 다르다면, 서로 다른 것으로 간주하기 때문에,
M이 7이고 K가 2라면,
4 + 4 + 4 + 4 + 4 + 4 + 4 = 28로,
두 번째 원소인 4와 네 번째 원소인 4를 번갈아 두 번씩 더하는 것이 가능하게 된다.
이 문제를 해결하려면, 우선 입력 값 중에서 가장 큰 수와 두 번째로 큰 수만 저장하면 된다.
연속으로 더할 수 있는 횟수는 K번이므로, 가장 큰 수를 K번 더하고, 두 번째로 큰 수를 한 번 더하는 연산을 반복하면 된다.
# N, M, K를 공백으로 받기
n, m, k = map(int, input().split())
# N개의 수를 공백으로 구분하여 입력받기
data = list(map(int,input().split()))
data.sort() # 입력받은 수를 정렬하기
first = data[n-1] # 가장 큰 수, 배열의 마지막 인덱스
second = data[n-2] # 두번째로 큰 수, 배열의 마지막-1 인덱스
result = 0
while True :
for i in range(k) : # 가장 큰 수를 K번 더하기
if m == 0 : #m이 0이라면 반복문 탈출
break
result += first
m -= 1 #더할 때 마다 1씩 빼기
if m == 0 : #m이 0이라면 반복문 탈출
break
result += second #두 번째로 큰 수를 한 번 더하기
m -= 1 # 더할 때 마다 m을 1씩 빼기
print(result) # 최종 답안 출력
4. 숫자 카드 게임
여러 개의 숫자 카드 중, 가장 높은 숫자가 쓰인 카드 한 장을 뽑는 게임
1. 숫자가 쓰인 카드들이 N X M 형태로 놓여있다.
2. N은 행의 개수, M은 열의 개수를 의미한다.
3. 먼저 뽑고자 하는 카드가 포함되어 있는 행을 선택한다.
4. 그 다음 선택된 행에 포함된 카드 중 가장 숫자가 낮은 카드를 뽑아야 한다.
즉, 이 문제는 각 행마다 가장 작은 수를 찾은 후, 그 수 중에서 가장 큰 수를 찾으면 된다.
이 문제는 리스트에서 가장 작은 원소를 찾아주는 min()함수를 이용할 수 있다.
# N, M을 공백으로 구분하여 입력받기
n, m = map(int, input().split())
result = 0
# 한 줄씩 입력받아 확인
for i in range(n):
data = list(map(int, input().split()))
# 현재 줄에서 '가장 작은 수' 찾기
min_value = min(data)
# '가장 작은 수'들 중에서 가장 큰 수 찾기
result = max(result, min_value)
print(result) # 최종 답안 출력
이 문제는 이중 반복문을 사용해서도 해결할 수 있다.
# N, M을 공백으로 구분하여 입력받기
n, m = map(int, input().split())
result = 0
# 한 줄씩 입력받아 확인
for i in range(n):
data = list(map(int, input().split())
#현재 줄에서 가장 작은 수 찾기
min_value = 10001
for a in data:
min_value = min(min_value, a)
# 가장 작은 수 들 중에서 가장 큰 수 찾기
result = max(rsult, min_value)
print(result) # 최종 답안 확인
5. 1이 될 때 까지
어떠한 수 N이 1이 될 때까지 두 과정 중 하나를 반복적으로 선택해서 수행한다.
2번째 과정은 N이 K로 나누어 질 때만 선택할 수 있다.
1. N에서 1을 뺀다.
2. N을 K로 나눈다.
입력 조건
첫째 줄에 N과 K가 공백으로 구분되며 각각 자연수로 주어진다.
이 때, 입력으로 주어지는 N은 항상 K보다 크거나 같다.
출력 조건
N과 K가 주어질 때, 1번 혹은 2번을 수행하야 하는 총 최솟값, 횟수를 구하여라
이 문제는 최대한 많이 나누는 것이 중요하다.
n, k = map(int, input().split())
result = 0
# N이 K 이상이라면 K로 계속 나누기
while n >= k :
# N이 K로 나누어 떨어지지 않는다면 N에서 1씩 빼기
while n % k != 0:
n -= 1
result += 1
# K로 나누기
n //= k
result += 1
#마지막에 남은 수에 대하여 1씩 빼기
while n > 1:
n -= 1
result += 1
print(result)
'<Algorithm>_study' 카테고리의 다른 글
[06] 동적 프로그래밍 (0) | 2021.11.28 |
---|---|
[05] 이진 탐색 (0) | 2021.11.17 |
[4] 정렬 (0) | 2021.11.09 |
[03] DFS/BFS (0) | 2021.11.03 |
[02] 구현(Implementation) (0) | 2021.10.12 |