가장 좋은 해
를 찾는 문제입력
: 거스름돈 액수 W CoinChange(W)
change = W;
c500 = c100 = c50 = c10 = c1 = 0; //동전 개수 담는 변수
while (change>=500) //500원으로 최대한 많이 거슬러 받기
{change -= 500; c500++;}
while (change>=100)
{change -= 100; c100++;}
while (change>=50)
{change -= 50; c50++;}
while (change>=10)
{change -= 10; c10++;}
while (change>=1)
{change -= 1; c1++;}
return (c500+c100+c50+c10+c1);
그리디
알고리즘을 적용한 CoinChange 알고리즘이 항상 최적 답을 제공하지 못한다
.신장트리
최소신장트리(MST)
가중치의 합 최소
Kruskal
, Prim
가중치 그래프 G = (V, E)
정점의 수 |V| = n
간선의 수 |E| = e
KruskalMST(G)
L[e] = 가중치 오름차순으로 간선 정렬;
T = NULL; //출력 트리(최소신장트리) 초기화
while(T의 간선 수 < n-1){
L에서 최소 가중치 간선 m 꺼내기;
L에서 m 삭제;
if (T에서 사이클 형성 시) //Union & Find
m 제외;
else
T에 m 추가;
}
return T; //MST 리턴
가중치 정렬
: => 최소 힙정렬while Loop
: 번Union & Find
: => 경로 압축 시 Find 시간 복잡도
가중치 그래프 G = (V, E)
정점의 수 |V| = n
간선의 수 |E| = e
최소신장트리 T
PrimMST1(G)
/*D[v]는 T에 있는 점 u, v 연결 최소가중치 간선 갱신 배열*/
D[p] = 0; //임의의 시작 정점
for(p 외의 정점 v){ //D[v] 초기화
if ((p, v) 존재)
D[v] = w[p, v];
else
D[v] = INTMAX;
}
T = {p};
while(|T| < n){
//최소 가중치 간선 추가
if ((u in T) && (v not in T)) && min{D[v]}
T = T + {(u, v), v};
// 가중치 재조정(갱신)
for (w not in T){
if (w[u, w] < D[w])
D[w] = w[u, w];
}
}
return T;
Prim
Dijkstra
가중치 그래프 G = (V, E)
정점의 수 |V| = n
간선의 수 |E| = e
출발 정점 s
s부터 v까지의 최단거리 저장 배열 D
ShortestPath(G, s){
/*D[v] 무한대로 초기화*/
D[s] = 0; 모든 D[v] = INTMAX;
while(s부터의 최단거리 확정되지 않은 점 있을 때){
확정 안 된 점 v에 대해 최소 D[v]인 점 v 선택;
D[v] 확정;
각 점 w, D[w] 최단거리 값으로 갱신;
}
return D;
}
힙 자료구조 사용하지 않는 경우
n-1
회O(n)
O(n)
힙(피보나치 힙) 사용하는 경우
0-1 배낭 문제
: 물건을 통째로 넣어야 한다.부분 배낭 문제
: 물건을 쪼개서 담기 가능단위 무게당 가치
구하기높은 순
으로 배낭에 넣기넣을 수 있을 만큼만 쪼개서
담기물건 개수: n
각 물건 무게: w
각 물건 가치: v
배낭 용량: C
배낭에 담은 물건 리스트: L
담은 물건 무게의 합: sum_w
담은 물건 가치의 합: sum_v
FractionalKnapsack(n, w, v, C)
S = 각 물건의 단위 무게당 가치 계산;
S = sorted(S, reverse = True); //내림차순 정렬
L = NULL; sum_w = 0; sum_v = 0; //초기화
x = S에서 단위 무게당 가치 가장 큰 물건;
while(sum_w + w(x) <= C){
// (무게 합 + x의 무게)가 배낭 총 용량보다 작거나 같을 때
L = L + {x};
sum_w += w(x);
sum_v += v(x);
S = S - {x};
x = S에서 단위 무게당 가치 가장 큰 물건;
}
if((C - sum_w) > 0){ //배낭에 쪼개서 담을 여유 있으면
L = L + {x};
sum_w += {(C-sum_w)만큼의 w(x)};
sum_v += {(C-sum_v)만큼의 w(v)};
}
return L, v; //담긴 물건 리스트, 가치의 합
O(n)
O(nlogn)
n
번O(1)
O(1)