백준 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로 모두 봉인이 되었을 경우, 남은 시간과 관계없이 종료되기 때문이다.
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
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