백준 25239번 가희와 카오스 파풀라투스(Java, Kotlin)

: ) YOUNG·2022년 6월 8일
2

알고리즘

목록 보기
145/422
post-thumbnail

백준 25239번
가희와 함께 하는 코딩테스트 4회
https://www.acmicpc.net/problem/25239

문제



시침은 12시 방향에서 2시 방향 사이를 가리킬 때 1번 영역에, 2시에서 4시 사이를 가리킬 때 2번 영역에, 4시 방향에서 6시 방향 사이를 가리킬 때 3번 영역에, 6시 방향에서 8시 방향 사이를 가리킬 때 4번 영역에, 8시 방향에서 10시 방향 사이를 가리킬 때 5번 영역에, 10시 방향에서 12시 방향 사이를 가리킬 때 6번 영역에 있습니다. 시침이 정확히 2, 4, 6, 8, 10, 12시를 가리키는 경우는 고려하지 않습니다.

시침이 x번 영역에 있을 때, 유저가 시계 왼쪽 포탈에서 윗키를 누르면, x번 영역이 봉인됩니다. 차원의 균열 패턴이 시전되고 1분이 지난 후, 봉인되지 않은 칸이 있다면, 그 칸들에 쓰여 있는 % 수치의 합만큼 체력을 회복하게 됩니다. 이때, % 수치의 합이 100을 넘어간다면 100%만큼 회복합니다. 만약, 1분이 지나기 전에 6개의 칸이 모두 봉인되었다면, 남은 시간과 관계 없이 패턴이 종료됩니다.

차원의 균열 패턴이 시전되고 난 후 가희가 플레이한 이벤트가 주어졌을 때, 패턴이 끝나고 파풀라투스는 몇 %의 체력을 회복할 수 있는지 구해 주세요.

차원의 균열 패턴이 끝난 후, 파풀라투스가 회복하는 체력이 h%라고 할 때, h를 출력해 주세요.


생각하기


대회를 참가했을 당시 이문제를 가지고 거진 3시간 정도를 붙잡고 있다가 다른 문제들 마저 풀 기회를 놓쳤다.

항상 프로그래머스를 통해서 코딩테스트를 접하다가 백준으로 보는 코딩테스트는 굉장히 낯설었다.
대회가 끝난뒤에도 한참을 고민하고 나서야 풀 수 있었다.

문제를 가지고 풀지 못했었던 이유는 문제를 수십번 읽어 봄에도 불구하고 이해하진 못한 내 문제였다.

문제 중에 아래와 같은 문항이 있었는데,
-다음 L개의 줄에는 발생한 이벤트 목록이 시간 순서대로 주어집니다. 이벤트 목록에 대한 형식은 아래와 같습니다.-

나는 밑에 나오는 문항들처럼 같은 형식으로 모든 시간이 나올 수 있다고 생각해서 아예 시간을 계산하는 프로그램을 구현했는데, 문제는 그게 아니었다.

처음 부터 틀렸던 시간과 분을 구분하는 코드

			char ch = T.charAt(T.length()-1);
			// MIN이나 HOUR냐를 구분
			
			// R일 경우, HOUR
			if( ch == 'R') {
				st = new StringTokenizer(T, "H");
				int hour = Integer.parseInt(st.nextToken());
				hour_calc(hour);
			}
			// N일 경우 MIN
			else {
				st = new StringTokenizer(T, "M");
				int min = Integer.parseInt(st.nextToken());
				min_calc(min);
			}

처음에는 HOUR이냐 MIN이냐 까지 모두 구분해서 구현해야 한다고 생각해서 너무 많은 고민을 했었다.

그냥 위에나오는 7가지 형식이 전부였던 것. 그 외의 시간은 나오지 않기 때문에 그냥 if문으로 처리해주기만 하면 문제가 없었다.

아마 나와 비슷한 생각으로 틀린사람이 여럿 있지 않을까 라는 생각을 조심스럽게 해본다..

동작

Time = (HOUR * 60) + MIN;

시간을 아예 분 단위로 변환한뒤 계산


		if((Time > 0) && (Time < 120)) Area = 1;
		else if((Time > 120) && (Time < 240)) Area = 2;
		else if((Time > 240) && (Time < 360)) Area = 3;
		else if((Time > 360) && (Time < 480)) Area = 4;
		else if((Time > 480) && (Time < 600)) Area = 5;
		else if((Time > 600) && (Time < 720)) Area = 6;

분 단위로 계산된 Time값을 기준으로 Area를 계산


			if(T.equals("^")) {
				check_area();
				visit[Area] = true;
				if(check_visit()) break;
				continue;
			}

"^"가 들어왔을 때 2가지 메소드를 실행한다.

먼저 Time에 따른 Area를 계산하고 해단 Area를 index로 사용해서 visit을 true처리 해주고, check_visit 메소드로 전체가 true인지 확인한다. 전체가 true로 모두 봉인이 되었을 경우, 남은 시간과 관계없이 종료되기 때문이다.



코드



Java

import java.util.*;
import java.io.*;

public class Main {
	static boolean visit[];
	static int Time;
	static int Area;

	public static void main(String[] args) throws Exception  {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
	
		st = new StringTokenizer(br.readLine(), ":");
		int HOUR = Integer.parseInt(st.nextToken());
		int MIN = Integer.parseInt(st.nextToken());
		Time = (HOUR * 60) + MIN;

		// 6개의 영역
		int arr[] = new int[7];
		visit = new boolean[7];
		st = new StringTokenizer(br.readLine());
		for(int i=1; i<=6; i++) {
			arr[i] = Integer.parseInt(st.nextToken());
		}

		int L = Integer.parseInt(br.readLine());
		while(L-->0) {
			st = new StringTokenizer(br.readLine());
			double s = Double.parseDouble(st.nextToken());			
			String T = st.nextToken();

			if(T.equals("^")) {
				check_area();
				visit[Area] = true;
				if(check_visit()) break;
				continue;
			}	

			if(T.equals("10MIN")) Time += 10;
			else if(T.equals("30MIN")) Time += 30;
			else if(T.equals("50MIN")) Time += 50;
			else if(T.equals("2HOUR")) Time += 120;
			else if(T.equals("4HOUR")) Time += 240;
			else if(T.equals("9HOUR")) Time += 540;

			// 12시간 기준 720분이 최대
			if(Time >= 720) Time -= 720;
		}

		int h = 0;
		for(int i=1; i<=6; i++) {
			if(!visit[i]) h += arr[i];
		}

		if(h >= 100) h = 100;

		System.out.print(h);
	} // End of main

	static void check_area() {

		if((Time > 0) && (Time < 120)) Area = 1;
		else if((Time > 120) && (Time < 240)) Area = 2;
		else if((Time > 240) && (Time < 360)) Area = 3;
		else if((Time > 360) && (Time < 480)) Area = 4;
		else if((Time > 480) && (Time < 600)) Area = 5;
		else if((Time > 600) && (Time < 720)) Area = 6;

	} // End of check_area

	static boolean check_visit() {

		for(int i=1; i<=6; i++) if(!visit[i]) return false;
		return true;
	} // End of check_visit
} // End of Main class

Kotlin

import java.util.*
import java.io.*

private lateinit var visit : BooleanArray
private var Time = 0; private var Area = 0
fun main() {
    val br = BufferedReader(InputStreamReader(System.`in`))
    var st: StringTokenizer

    st = StringTokenizer(br.readLine(), ":")
    val hour = st.nextToken().toInt()
    val min = st.nextToken().toInt()
    Time = (hour*60) + min

    var arr = IntArray(7)
    visit = BooleanArray(7)

    st = StringTokenizer(br.readLine())
    for(i in 1..6) arr[i] = st.nextToken().toInt()

    var L = br.readLine().toInt()
    while(L-->0) {
        st = StringTokenizer(br.readLine())
        st.nextToken()
        var T = st.nextToken().toString()

        if(T == "^") {
            checkArea()
            visit[Area] = true
            if(checkVisit()) break
        }

        if(T == "10MIN") Time += 10
        else if(T == "30MIN") Time += 30
        else if(T == "50MIN") Time += 50
        else if(T == "2HOUR") Time += 120
        else if(T == "4HOUR") Time += 240
        else if(T == "9HOUR") Time += 540

        if(Time >= 720) Time -= 720
    }

    var h = 0
    for(i in 1..6)  if(!visit[i]) h += arr[i]

    if(h >= 100) h = 100

    print(h)
} // End of main

private fun checkVisit() : Boolean {
    for(i in 1..6) {
        if(!visit[i]) return false;
    }
    return true;
} // End of checkVisit

private fun checkArea() {
    Area = when(Time) {
        in 0 until 120 -> 1
        in 121 until 240 -> 2
        in 241 until 360 -> 3
        in 361 until 480 -> 4
        in 481 until 600 -> 5
        else -> 6
    }
} // End of checkArea

0개의 댓글