[백준] 16434 드래곤 앤 던전 - Java

2024. 1. 25. 14:57· Algorithm/백준 문제풀이
목차
  1. 문제 출저
  2. 문제 풀이
  3. 소스코드

 

 

 

문제 출저

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

 

16434번: 드래곤 앤 던전

첫 번째 줄에 방의 개수 N (1 ≤ N  ≤ 123,456) 과 용사의 초기 공격력 HATK (1 ≤ HATK  ≤ 1,000,000) 가 주어집니다. i+1번째 줄엔 i번째 방의 정보를 나타내는 세개의 정수 ti, ai, hi (ti ∈ {1, 2}, 1

www.acmicpc.net

 

 

 

문제 풀이

용사의 공격력이 주어집니다. 그리고 방의 정보가 주어집니다. 방에는 포션이 있을 수가 있고 몬스터가 있을 수 있습니다. 포션이 있으면 용사의 공격력과 체력이 올라갑니다. 이 때, 체력은 최대 체력을 넘을 수 없습니다. 몬스터가 있을 경우 몬스터와 전투를 합니다. 용사가 먼저 공격하면서 서로 공격을 주고 받습니다. 둘 중 체력이 0 이하가 되면 전투가 끝납니다. 몬스터가 0 이하가 되면 용사는 탐색을 계속 합니다. 용사가 체력이 0 이하가 되면 다시 최대 체력을 설정해서 처음부터 도전합니다. 이 때, 방을 다 탐색하기 위해 용사의 최대 체력의 최솟값을 구해야 합니다. 

 

 

이분 탐색으로 문제를 풀었습니다.

용사의 최소 체력은 1입니다. 용사의 최대 체력은 용사의 공격력이 1이라고 가정 했을 때, 몬스터 공격력 * 몬스터 체력을 전부 더 한 값입니다. 이것이 최악의 경우에서 나올 수 있는 용사의 최대 체력입니다. 이분 탐색으로 최소 최대 체력을 찾습니다. 모든 방을 탐색할 수 있는지에 대한 여부를 true, false로 하여 탐색할 수 있으면 true, 탐색할 수 없다면 false를 반환합니다. true 면은 체력을 낮추고 다시 확인합니다. false면 체력을 높이고 다시 확인합니다.

 

모든 방을 탐색할 수 있는지에 대한 여부는 클래스를 이용했습니다. Room, Braver 클래스를 만들고 Braver에는 potion, battle 이라는 메소드를 만들어 포션을 먹을 때, 전투를 했을 때 로직을 처리했습니다. battle 로직을 만들 땐 while문을 이용했는데 이러면 여러 번 연산이 진행되어 비효율적입니다. while 반복이 아니라 계산을 통해 결과값을 유추하도록 로직을 다시 재구성했습니다. 

 

 

 

소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

/*
드래곤 앤 던전
https://www.acmicpc.net/problem/16434

이분 탐색
최댓값 설정 : 용사의 공격력을 1이라 생각하면 몬스터 공격 * 체력이 된다.

 */
public class Main {

  static int n;
  static int atk;
  static List<Room> rooms;
  static long hpMax;


  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());
    atk = Integer.parseInt(st.nextToken());

    rooms = new ArrayList<>();
    long max = 0;

    for(int i = 0; i < n; i++) {
      st = new StringTokenizer(br.readLine());
      int t = Integer.parseInt(st.nextToken());
      int a = Integer.parseInt(st.nextToken());
      int h = Integer.parseInt(st.nextToken());
      rooms.add(new Room(t, a, h));
      if(t == 1) max += ((long)a * h);
    }


    long min = 1;
    long answer = 0;

    while(min <= max) {
      hpMax = (max + min) / 2;

      if(check()) {
        max = hpMax - 1;
        answer = hpMax;
      }
      else {
        min = hpMax + 1;
      }
    }

    System.out.println(answer);

  }

  // 이 정도 체력이면 깰 수 있는지 여부
  public static boolean check() {
    Braver braver = new Braver(atk, hpMax);

    for(Room room : rooms) {
      if(room.t == 1) {
        if(!braver.battle(room.a, room.h)) return false;
      }
      if(room.t == 2) braver.potion(room.a, room.h);
    }

    return true;

  }


  // 방의 정보
  public static class Room {

    int t; // 1: 몬스터 2: 포션
    int a; // 공격력, 공격력 증가
    int h; // 생명력, 생명력 증가

    Room(int t, int a, int h) {
      this.t = t;
      this.a = a;
      this.h = h;
    }
  }

  public static class Braver {
    long atk; // 공격력
    long hp; // 체력

    Braver(long atk, long hp) {
      this.atk = atk;
      this.hp = hp;
    }

    // 포션을 마셨을 경우 공격력과 체력이 올라감
    // 체력은 최대 hp를 넘을 수 없다.
    void potion(int a, int h) {
      this.atk += a;
      this.hp = Math.min(hp+h, hpMax);
    }

    // 전투
    // while 쓸 경우 비효율적이다.
    boolean battle(int a, int h) {
      long braverAttack = h / atk;
      if(h % atk != 0) braverAttack += 1;
      long monsterAttack = hp / a;
      if(hp % a != 0) monsterAttack += 1;

      if(monsterAttack < braverAttack) {
        return false;
      }
      else {
        hp -= (a * (braverAttack - 1));
        return true;
      }
    }
  }

}
  1. 문제 출저
  2. 문제 풀이
  3. 소스코드
'Algorithm/백준 문제풀이' 카테고리의 다른 글
  • [백준] 8394 악수 - Java
  • [백준] 1700 멀티탭 스케줄링 - Java
  • [백준] 15748 Rest Stops - Java
  • [백준] 1245 농장 관리 - Java
너지살
너지살
너지살
너지살개발자
너지살
전체
오늘
어제
  • 분류 전체보기 (375)
    • 잡식 (2)
      • 티스토리 (2)
    • 개발 일지 (0)
      • OMS 프로젝트 (4)
      • 우테코 6기 프리코스 (1)
    • Git (2)
    • JAVA (15)
      • Java 공부 (6)
      • 자료구조 (4)
      • 도움되는 메모 (4)
    • DevOps (18)
      • AWS (6)
      • Docker (2)
      • Jenkins (1)
      • Nginx (1)
      • Kafka (6)
      • RabbitMQ (2)
    • Spring, Spring Boot (16)
      • Test Code (1)
      • AOP (2)
      • Batch (3)
      • Cache - Redis (5)
      • Cloud Config - 설정 파일 관리 (3)
      • 성능 측정 (1)
      • 예외 처리 (1)
    • BackEnd (1)
      • Spring 공부 (1)
      • Thymeleaft (0)
    • DB (17)
      • JPA (2)
      • DB 공부 (3)
      • DB 포스팅 (4)
      • DB 답장 (1)
      • MySQL (2)
      • Redis (5)
      • MongoDB (0)
    • CS (8)
      • Spring (4)
      • DataBase (3)
      • Java (1)
    • Algorithm (203)
      • 알고리즘 개념 (5)
      • 정렬 알고리즘 (11)
      • 프로그래머스 문제풀이 (18)
      • 백준 문제풀이 (165)
      • 소프티어 문제풀이 (3)
      • 알고리즘 시험 정리 (1)
    • SQL (0)
      • 문법 (1)
      • 프로그래머스 문제풀이 (52)
      • 리트코드 문제풀이 (19)
    • IT (1)
      • IT 공부 (1)
    • 정리 (10)
      • 질문 정리 (10)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 백준
  • 다이나믹프로그래밍
  • 병렬 처리
  • 그래프 탐색
  • JPA
  • 깊이/너비 우선탐색
  • 우선수위큐
  • 설정
  • DFS
  • 그래프 이론
  • 질문 정리
  • Union-Find
  • 자료구조
  • Java 정리
  • 경로표현식
  • dynamiceprogramming
  • MST
  • docker
  • Test code
  • DP
  • Next permutation
  • 소프티어
  • Spring Boot Redis 연결
  • 다이나믹 프로그래밍
  • cache
  • Spring Batch
  • 알고리즘
  • 크루스칼 알고리즘
  • 외판원 순회 문제
  • 분리 집합
  • 두 포인터
  • 유니온파인드
  • Spring Boot
  • 투포인트
  • Java
  • Bitmast
  • 다음 순열 찾기
  • two pointer
  • db
  • redis
  • 투 포인터
  • 데이터베이스
  • 비트마스킹
  • dynamic programing
  • 최소 신장 트리
  • Sorting algorithm
  • Algorithm
  • 부분탐색
  • git
  • 최소 스패닝 트리

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.2
너지살
[백준] 16434 드래곤 앤 던전 - Java
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.