그리디 알고리즘은 현재 상황에서 지금 당장 좋은 것만 고르는 방법
[문제 상황] 루트 노드부터 시작하여 거쳐 가는 노드 값의 합을 최대로 만들고 싶다.
Q. 최적의 해는 무엇인가요?
Q. 단순히 매 상황에서 가장 큰 값만 고른다면 어떻게 될까요?
이 경우 그리디 알고리즘이라 할 수 있다.
가장 큰 화폐 단위부터 돈을 거슬러 주는 것이 최적의 해를 보장하는 이유는?
가지고 있는 동전 중에서 큰 단위가 항상 작은 단위의 배수이므로 작은 단위의 동전들을 종합해 다른 해가 나올 수 없기 때문이다.
만약에 800원을 거슬러 주어야 하는데 화폐 단위가 500원, 400원, 100원이라면?
이 경우는 500원이 400원의 배수가 아니기 때문에 400원 동전 2개로 거슬러 주는 것이 최적의 방법이다.
그리디 알고리즘 문제에서는 이처럼 문제 풀이를 위한 최소한의 아이디어를 떠올리고 이것이 정당한지 검토할 수 있어야 한다.
public class Main {
public static void main(String[] args) {
int n = 1260;
int cnt = 0;
//큰 단위의 화폐부터 차례대로 확인하기
int[] coinTypes = {500, 100, 50, 10};
for (int i = 0; i < 4; i++) {
int coin = coinTypes[i]; //해당 화폐로 거슬러 줄 수 있는 동전의 개수 세기
cnt += n / coin;
n %= coin;
}
System.out.println(cnt);
}
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// N, K를 공백을 기준으로 구분하여 입력 받기
int n = sc.nextInt();
int k = sc.nextInt();
int result = 0;
while (true) {
// N이 K로 나누어 떨어지는 수가 될 때까지만 1씩 빼기
int target = (n / k) * k;
result += (n - target);
n = target;
// N이 K보다 작을 때 (더 이상 나눌 수 없을 때) 반복문 탈출
if (n < k) break;
// K로 나누기
result += 1;
n /= k;
}
// 마지막으로 남은 수에 대하여 1씩 빼기
result += (n - 1);
System.out.println(result);
}
}
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
String str = sc.next();
// 첫 번째 문자를 숫자로 변경한 값을 대입
long result = str.charAt(0) - '0';
for(int i = 1; i < str.length(); i++){
// 두 수 중에서 하나라도 0 혹은 1인 경우, 곱하기보다 더하기 수행
int num = str.charAt(i) - '0';
if(num <= 1 || result <= 1){
result += num;
}
else{
result *= num;
}
}
System.out.println(result);
}
}
오름차순 정렬 이후에 공포도가 가장 낮은 모험가부터 하나씩 확인
앞에서부터 공포도를 하나씩 확인하며
현재 그룹에 포함된 모험가의 수 >= 현재 확인하고 있는 공포도
인 경우 이를 같은 그룹으로 설정
이러한 방법을 이용하면 공포도가 오름차순으로 정렬되어 있다는 점에서, 항상 최소한의 모험가의 수만 포함하여 그룹을 결성하게 된다.
import java.util.*;
class Main {
public static int n;
public static ArrayList<Interger> arrayList = new ArrayList<>();
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
for(int i = 0; i < n; i++){
arrayList.add(sc.nextInt());
}
Collections.sort(arrayList);
int result = 0; // 총 그룹의 수
int count = 0; // 현재 그룹에 포함된 모험가의 수
for(int i = 0; i < n; i++){ // 공포도를 낮은 것부터 하나씩 확인하며
count += 1; // 현재 그룹에 해당 모험가를 포함시키기
if(count >= arrayList.get(i)){ // 현재 그룹에 포함된 모험가의 수가 현재의 공포도 이상이라면, 그룹 결성성
result += 1; // 총 그룹의 수 증가시키기
count = 0; // 현재 그룹에 포함된 모험가의 수 초기화
}
}
System.out.println(result);
}
}