(백준) 컵라면 - 1781 [java]

2021. 8. 21. 12:26·알고리즘/백준

https://www.acmicpc.net/problem/1781

🐢 설명

제한기간이 있는 문제를 풀어서 최대한 많은 컵라면을 얻어야 되는 문제이다.

 

먼저 우선순위큐를 사용해서 컵라면을 가장 많이 주는 순서로 정렬하고 해당 문제의 마감날을 통해 해당날에 이미 문제를 풀었으면 그 전날 ~ 1일 까지 확인하면서 문제를 풀수 있는날을 찾아주면된다.

 

하지만 단순하게 우선순위큐에서 하나씩 뽑고 날짜 확인하고 이미 차있으면 배열을 돌면서 빈날을 확인하게 하면 시간초과가 나게 된다.

  • 총 과제의 개수가 20만개인데 최악의 경우 20만개 * d-day 20만으로 O(N^2)이 된다.

 

Union-Find를 사용하면 이를 O(N)으로 풀수 있다. 어떻게 접근하면 되는지 정리해보자.

 

  1. d-day날이 총 과제의 개수 보다 크거나 같다면 전부 풀 수 있으므로 바로 컵라면 개수를 더한다.
  2. 아닐 경우
    1. day날 풀수 있다면 바로 그날 푼다. find(day)가 자신의 day와 같다면 풀 수 있음
      • 풀고 나서 하루 전날과 합친다. union(find(전날), 당일)
    2. d-day날 풀수 없다면 ( find(day)가 자신의 day와 다름 ), 하루 전날의 parents인 find(day - 1)과 자신의 day의 parents인 find(day)와 비교한다.
      • 전날의 parent가 자신의 day와 같다면 풀고나서 하루 전날의 parent에 합친다.
      • 만약 그날이 0일 이라면 풀 수 없으므로 넘어간다. (해당 문제는 못품)

자신의 기존 날에 풀수 있으면 풀고, 아니면 parents를 비교해서 O(1)로 이동해서 풀거나 / 0일 이라 못풀거나가 되므로 O(N)으로 풀이가 가능하다.

 

🐢코드
//package Gold이상문제_정리;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {
    static int N, LastDay;
    static PriorityQueue<Cup> pq = new PriorityQueue<>(Comparator.comparingInt(c -> -c.count));
    static int[] days;

    private static class Cup {
        int deadLine;
        int count;

        public Cup(int deadLine, int count) {
            this.deadLine = deadLine;
            this.count = count;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());

        N = Integer.parseInt(st.nextToken());

        for (int i = 0; i < N; i++) {
            st = new StringTokenizer(br.readLine());
            int dead = Integer.parseInt(st.nextToken());
            int count = Integer.parseInt(st.nextToken());
            pq.add(new Cup(dead, count));
            LastDay = Math.max(LastDay, dead);
        }

        days = new int[LastDay + 1];
        for (int i = 0; i < LastDay + 1; i++) days[i] = i;

        int answer = solve();
        System.out.println(answer);
    }

    private static int solve() {
        int totalCup = 0;
        int today;
        while (!pq.isEmpty()) {
            Cup now = pq.poll();
            today = now.deadLine;

            if (today >= N) {
                totalCup += now.count;
                continue;
            }

            if (find(today) == today) { // 당일 풀기 가능
                union(find(today - 1), today);
                totalCup += now.count;
            } else if (find(today) != 0) { // 가능한 전일에 미리 풀기 (단, 0일이 아니라면)
                today = find(today);
                union(find(today - 1), today);
                totalCup += now.count;
            }
        }
        return totalCup;
    }

    private static int find(int now) {
        if (days[now] == now) return now;
        return days[now] = find(days[now]);
    }

    private static void union(int left, int right) {
        left = find(left);
        right = find(right);

        days[days[right]] = days[left];
    }
}
🐢 마무리

유니온 파인드를 이용해서 풀수 있는 재밌는 문제였다.

반응형
저작자표시 (새창열림)

'알고리즘 > 백준' 카테고리의 다른 글

(백준) 맥주마시면서걸어가기_9205 [java]  (1) 2021.08.24
(백준) 연료채우기_1826 [java]  (1) 2021.08.23
(백준) 최소 환승 경로 - 2021 [java]  (1) 2021.08.18
(백준) 달이 차오른다, 가자 - 1194 [java]  (0) 2021.08.17
(백준) 미친 아두이노 - 8972 [java]  (1) 2021.08.10
'알고리즘/백준' 카테고리의 다른 글
  • (백준) 맥주마시면서걸어가기_9205 [java]
  • (백준) 연료채우기_1826 [java]
  • (백준) 최소 환승 경로 - 2021 [java]
  • (백준) 달이 차오른다, 가자 - 1194 [java]
구름뭉치
구름뭉치
구름의 개발일기장
    반응형
  • 구름뭉치
    구름 개발일기장
    구름뭉치
  • 전체
    오늘
    어제
    • ALL (288) N
      • 프로젝트 (23)
        • 토스페이먼츠 PG 연동 시리즈 (12)
        • JWT 방식 인증&인가 시리즈 (6)
        • 스우미 웹 애플리케이션 프로젝트 (1)
        • 스프링부트 기본 보일러 플레이트 구축 시리즈 (2)
        • 마이크로서비스 아키텍쳐 시리즈 (1)
      • 스프링 (43)
        • 스프링부트 API 설계 정리 (8)
        • 스프링부트 RestAPI 프로젝트 (18)
        • 스프링부트 WebSocket 적용기 (3)
        • 스프링 JPA 정리 시리즈 (5)
        • 스프링 MVC (5)
        • 스프링 배치 (2)
        • 토비의 스프링 정리 (2)
      • 기술 학습 (4) N
        • 아파치 카프카 (9)
        • 클린 코드 (4)
        • 디자인 패턴의 아름다움 (2)
        • 모던 자바 인 액션 (7)
        • JVM 스레드 딥다이브 (7)
      • Web (25)
        • 정리글 (20)
        • GraphQL 정리글 (2)
        • Jenkins 정리글 (3)
      • 취업 (6)
      • CS (77)
        • 네트워크 전공 수업 정리 (11)
        • OSI 7계층 정리 (12)
        • 운영체제 정리 (19)
        • 데이터베이스 정리 (5)
        • MySql 정리 (17)
        • GoF의 Design Pattern 정리 (12)
      • 알고리즘 (70)
        • 백준 (56)
        • 프로그래머스 (12)
        • 알고리즘 정리본 (1)
      • 기초 지식 정리 (2)
      • 일상 (8)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    동유럽
    레이저
    마우스
    mx master s3 for mac
    크로아티아
    키보드 손목 받침대
    류블라냐
    부다페스트
    마우스 패드
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
구름뭉치
(백준) 컵라면 - 1781 [java]
상단으로

티스토리툴바