18111번 마인크래프트
🅰 설계
1. 어떤 방법을 사용할 것인가?
땅의 높이가 최대 256이므로 0부터 256까지 높이를 한 번씩 설정해보고 그 높이로 평탄화하는 방법을 생각할 수 있다.
맵의 크기는 최대 500이므로 250,000이다. 250,000*257 = 64,250,000이므로 1초 제한인 이 문제에서 모든 블럭을 한 번씩 돌면서 높이를 체크하는 방법을 쓰기는 불안하다.
모든 맵을 돌지 않아도 땅의 최대 높이가 256이므로 각 높이에 해당하는 블록의 개수를 미리 저장해둘 수 있다.
그리고 0~256까지 높이를 한 번씩 시도해보면서 현재 가지고있는 블럭들의 높이에 대해서 현재 설정한 높이를 만드는데 드는 비용을 계산할 수 있다.
2. 전체 코드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | import java.util.*; import java.io.*; public class 마인크래프트 { static BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); static StringTokenizer st; public static void main(String[] args) throws IOException{ int N,M,B; st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); B = Integer.parseInt(st.nextToken()); int height[] = new int[257]; for(int i=0;i<N;i++){ st = new StringTokenizer(br.readLine()); for(int j=0;j<M;j++){ int cur = Integer.parseInt(st.nextToken()); height[cur]++; } } int anstime = Integer.MAX_VALUE; int ansheight = 0; for(int i=256;i>=0;i--){ int curB = B; int subtime = 0; for(int j=256;j>=0;j--){ if(height[j] > 0){ if(j < i){ curB -= height[j]*(i-j); subtime += height[j]*(i-j); }else if(j > i){ curB += height[j]*(j-i); subtime += height[j]*(j-i)*2; } } } if(curB < 0) continue; if(anstime > subtime){ anstime = subtime; ansheight = i; } } System.out.println(anstime + " " + ansheight); } } | cs |
높이를 256부터 0까지 시도하므로 시간이 최소인 부분만 체크하면 같은 시간이 걸리는 높이에 대해서 항상 가장 큰 높이로 평탄화하는 행동이 답이 된다.
✅ 후기
처음에 BruteForce 문제인줄 알고 각 맵을 모두 도는 방법을 생각했었는데 시간 복잡도를 계산해보고 다른 방법을 생각했다. 아이디어가 좋았던 문제였다.
'Problem Solving > Baekjoon' 카테고리의 다른 글
[ACMICPC] 10250 . ACM 호텔 (0) | 2021.08.07 |
---|---|
[ACMICPC] 13469 . 시간표 짜기 (0) | 2021.08.06 |
[ACMICPC] 2468 . 안전 영역 (0) | 2021.08.04 |
[ACMICPC] 2470 . 두 용액 (0) | 2021.08.03 |
[ACMICPC] 5525 . IOIOI (0) | 2021.08.02 |