23년 7월 11일 [알고리즘 - 그리디]

sua·2023년 7월 11일
0

알고리즘 가보자고

목록 보기
52/101

백준 2875번 대회 or 인턴

문제


나의 풀이

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int m = sc.nextInt();
        int n = sc.nextInt();
        int k = sc.nextInt();
        int answer = 0;
        while(m >= 2 && n >= 1 && m + n >= k + 3) {
            answer += 1;
            m -= 2;
            n -= 1;
        }
        System.out.println(answer);
    }
}

한팀을 만드려면 여학생이 2명 이상이고, 남학생이 1명 이상, 남학생과 여학생의 합이 k에 3을 더한 값 보다 커야 하는 조건들을 만족해야 한다.

  • M+N >= K+3 (팀은 3명이고 인턴은 k명이 해야하기 때문에)
    따라서 while 문의 조건으로 m이 2이상이고 n이 1이상이며 m+n이 k+3보다 클때까지 반복시켜서 answer의 값을 증가시켜서 답을 구하면 된다.

결과


백준 10610번 30

문제


나의 풀이

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        char s[] = sc.nextLine().toCharArray();
        
        int sum = 0;
        for(int i = 0; i < s.length; i++) {
            sum += s[i] - '0'; // 각 자리 수의 합 구하기
        }
        
        Arrays.sort(s); // 오름차순 정렬(0이 있다면 제일 첫번째 인덱스에 0이 있을 것이다.)
        
        if(s[0] == '0' && sum % 3 == 0) { // 30의 배수인 경우
            for(int i = s.length - 1; i >= 0; i--) { // 가장 큰 수이므로 뒤에서부터 출력
                System.out.print(s[i]);
            }
        } else {
            System.out.println(-1);
        }
    }
}

30의 배수란 뜻은 2와 3과 5의 배수여야 한다는 뜻이다.
2의 배수는 끝 자리가 2, 4, 6, 8, 0이고
5의 배수는 끝 자리가 5, 0이 되어야 한다.
이 둘을 합쳐서 생각해보면 30의 배수는 마지막 숫자가 0이 되어야 한다는 것이다.
3의 배수는 모든 자리를 다 더한 값이 3의 배수여야 한다.
즉, 30의 배수는 모든 자리를 다 더한 값이 3의 배수(3으로 나누어 떨어져야함)이면서 마지막 숫자가 0인 숫자를 찾으면 된다.
먼저 수를 입력 받아서 각 수들을 오름차순으로 정렬한 뒤 첫번째 숫자가 0이 면서(마지막 숫자가 0인 조건 만족) 각 숫자들의 합이 3으로 나누어 떨어지는 경우 각 수들을 저장한 배열이 현재 오름차순이므로 뒤에서부터 출력시켜주면 된다. 이를 만족하지 않는 경우는 30의 배수가 될 수 없으므로 -1을 출력하면 된다.

결과


백준 1783번 병든 나이트

문제


나의 풀이

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int height = sc.nextInt();
        int width = sc.nextInt();
        if(height == 1) {
            System.out.println(1);
        } else if(height == 2) {
            System.out.println(Math.min(4, (width + 1) / 2));
        } else if(height >= 3) {
            if(width >= 7) {
                System.out.println(width - 2);
            } else {
                System.out.println(Math.min(4, width));
            }
        }
    }
}

높이가 무엇인지에 따라 경우의 수를 나누어서 생각해야 한다.

  1. height = 1인 경우 : 움직일 수 없기 때문에 정답은 1
  2. height = 2인 경우 : 두 가지 방법[(+2,+1),(+2,1)]만 사용할 수 있기 때문에 정답은 min(4, (width + 1) / 2). 이동 횟수 제한 때문에 4가 필요하다.
  3. height >= 3인 경우
    • width >= 7 : 4가지 방법을 모두 사용하면 (7,1)로 이동한다. 여기서부터 (+1,+2)와 (+1,-2)를 번갈아가면서 사용할 수 있다. => width - 2
    • width < 7 : 4가지 방법을 모두 사용할 수 없다. (+1, +2)와 (+1, -2)를 번갈아 가면서 사용할 수 없기 때문에 min(4, width)

이를 구현하면 된다.

결과


인프런 과일 가져가기

문제

나의 풀이

public class TakeFruit {
    public static int getMin(int[] fruit) { // 각 학생의 최솟값 구하기
        int min = 100;
        for(int x : fruit) {
            min = Math.min(min, x);
        }
        return min;
    }
    public static Boolean isMinUnique(int[] fruit) { // 최솟값이 유니크한지 구하기
        int count = 0;
        int min = getMin(fruit);
        for(int x : fruit) {
            if(x == min) {
                count++;
            }
        }
        return count == 1;
    }
    public static int getMinIndex(int[] fruit) { // 최솟값을 가진 인덱스 구하기
        int min = getMin(fruit);
        for(int i = 0; i < 3; i++) {
            if(fruit[i] == min) {
                return i;
            }
        }
        return 0;
    }
    static public int solution(int[][] fruit) {
        int answer = 0;
        int n = fruit.length;
        int ch[] = new int[n];
        for(int i = 0; i < n; i++) {
            if(ch[i] == 1) { // 이미 교환한 사람인 경우
                continue;
            }
            if(isMinUnique(fruit[i]) == false) { // 최솟값이 유일하지 않은 경우
                continue;
            }
            for(int j = i + 1; j < n; j++) {
                if (ch[j] == 1) { // 이미 교환한 사람인 경우
                    continue;
                }
                if (isMinUnique(fruit[j]) == false) {
                    continue;
                }
                int a = getMinIndex(fruit[i]);
                int b = getMinIndex(fruit[j]);
                if (a != b && fruit[i][b] > 0 && fruit[j][a] > 0) { // 서로 다른 과일이 최솟값인 경우
                    if (fruit[i][a] + 1 <= fruit[i][b] - 1 && fruit[j][b] + 1 <= fruit[j][a] - 1) { // 교환하고 난 뒤에도 최솟값 유지되는 경우
                        fruit[i][a]++;
                        fruit[i][b]--;
                        fruit[j][b]++;
                        fruit[j][a]--;
                        ch[i] = 1;
                        ch[j] = 1;
                        break;
                    }
                }
            }
        }
        for(int x[] : fruit) {
            answer += getMin(x); // 총합 구하기
        }
        return answer;
    }

    public static void main(String[] args) {
        System.out.println(TakeFruit.solution(new int[][] {{10, 9, 11}, {15, 20, 25}}));
    }
}

서로 교환했을 때 이득이 나는 조건은
1. 각 학생의 최솟값이 유니트(유일) 해야 한다.
2. 서로 교환하려고 하는 두 학생의 최솟값인 과일이 서로 달라야 한다.
3. 교환했을 때 1개 증가한 과일의 개수가 그대로 최솟값을 유지해야 한다.
이 조건에 맞춰서 구현하면 된다.

결과

profile
가보자고

0개의 댓글