출처: https://www.acmicpc.net/problem/2805
2805번: 나무 자르기
첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000) 둘째 줄에는 나무의 높이가 주어진다. 나무의 높이의 합은 항상 M보
www.acmicpc.net
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class BOJ_TEMP {
public static void main(String[] args) throws Exception{
// INPUT & INIT
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int target = Integer.parseInt(st.nextToken());
Integer[] arr = new Integer[a+1];
st = new StringTokenizer(br.readLine());
for(int i=0; i<arr.length-1; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
arr[arr.length-1] = 0;
// SORT
Arrays.sort(arr, Collections.reverseOrder());
// CALCULATE
long answer = 0;
long sum = 0;
for(int i=0; i<arr.length-1; i++) {
long temp = arr[i] - arr[i+1];
long tempSum = sum + (temp * (i+1));
// 여태까지 자른 길이의 합이 딱 맞다면 다음원소의 길이를 출력하고 마무리
if(target == tempSum) {
answer = arr[i+1];
break;
}else if(target < tempSum || i==arr.length-2){
// 길이의 합이 더 길다면 or 마지막
long n = Math.abs(tempSum - target);
answer = arr[i+1] + (int)(Math.ceil(n/(i+1)));
break;
}else { // 길이의 합이 아직 더 적다면 한번 더 잘라본다
sum = tempSum;
}
}
// OUTPUT
System.out.println(answer);
}
}
주의 : 이분 탐색 아님!!! 개느림!!! (2160ms)
나는 거의 그리디? 완전탐색? 잘모르겠네.. 여튼 그런식으로 풀었음
푸는 방식은 입력을 받고 내림차순으로 정렬한다. (소스 보면 알겠지만 맨 뒤에 0이 더 있음)
앞에서부터 다음 원소의 높이와 같아지게 자르고 여태까지 잘랐던 나무를 더한다
그리고 그 값이 목표치와 비교해서
1. 딱 맞다면 다음 원소의 높이와 같다면 다음원소의 높이까지만 자르면되고
2. 아직 모자르다면 반복문의 다음 루프로 보낸다
3. 더 많이 잘랐거나 마지막 0과 비교할 때는
다음원소의 값과 덜 자를만큼의 길이를 비교해서 계산한다
백준 input으로 예시를 들면
예시 1
예시 2
이런 방식으로 자르고 특이케이스 부분들만 처리해주면된다
5 2000000000 900000000 900000000 900000000 900000000 900000000
이런 경우 값이 다 똑같기 때문에 마지막 원소까지 가게되었을 경우 절대값 처리를 해서 계산했다
일단 통과는 했는데 이분탐색으로 다시 생각하고 풀어봐야겠다