C#/알고리즘

16. 2805번 나무 자르기

dev_sr 2020. 9. 6. 15:34

 

 

2805번: 나무 자르기

첫째 줄에 나무의 수 N과 상근이가 집으로 가져가려고 하는 나무의 길이 M이 주어진다. (1 ≤ N ≤ 1,000,000, 1 ≤ M ≤ 2,000,000,000) 둘째 줄에는 나무의 높이가 주어진다. 나무의 높이의 합은 항상 M을

www.acmicpc.net

이분탐색 문제

 

[알고리즘] 이분 탐색

이분 탐색  탐색 기법중에 하나로 원하는 탐색범위를 두 부분으로 분할해서 찾는 방식입니다. 그렇기에 원래의 전부를 탐색하는 탐색 속도에 비해 빠릅니다. 이분 탐색을 하는 방법은 left , right

wootool.tistory.com

나무를 입력받고 left(0), right(나무 중 최대 길이값), mid(왼쪽, 오른쪽 평균값) 을 구해준 뒤

평균값으로 나무들을 다 자름

 

1. 자른 나무의 길이의 합 (sum) >= 가져갈 나무의 길이(M) 

2. 자른 나무의 길이의 합 (sum) < 가져갈 나무의 길이(M)  

 

이렇게 나눠서 생각할 수 있었음

 

1번일 경우 left = mid +1 해주고 정답값에 mid를 넣어줌

2번일 경우 right = mid -1 해주면서

 

탐색 범위를 좁혀감

 

left가 right보다 커지면 탐색 종료고 값을 출력함 

 

처음에 틀려서 반례 찾다가 입력값이 워낙 커서 long으로 안하면 스택오버플로우 난다고 봐서

나무 길이 입력값은 다 long으로 바꿈 (int64.parse 써야함  int32.parse ㄴㄴ)

 

이분탐색이 낯선 거 빼곤 아주 많이 어렵진 않았음..

 

*

4 10

1 4 5 7

반례로 예시 말고 이것도 입력해보기 (답은 2)

 

 

using System;
using System.Collections.Generic;
using System.Linq;

namespace _2805
{
    public class Tree
    {
        public long length;

        public Tree(long length)
        {
            this.length = length;
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            List<Tree> treelist = new List<Tree>();

            string[] input = Console.ReadLine().Split(' ');
            int N = Int32.Parse(input[0]);  //나무 갯수
            int M = Int32.Parse(input[1]);  //집으로 가져갈 나무 길이

            string[] input2 = Console.ReadLine().Split(' ');
            for (int i = 0; i < N; i++)
            {
                Tree tree = new Tree(Int64.Parse(input2[i]));
                treelist.Add(tree);
            }

            Binary(treelist, N, M);
        }

        static void Binary(List<Tree> treelist, int N, int M)
        {
            long right = treelist.Max(x => x.length);
            long left = 0;

            long result = 0;

            while(left<=right)
            {
                long mid = (right + left) / 2;
                long sum = 0;    //자르고 난 나무 길이의 합
                Console.WriteLine("mid: "+mid);
                Console.WriteLine("left: "+left);
                Console.WriteLine("right: "+right);

                for(int i=0; i<N; i++)
                {
                    if(mid<treelist[i].length)
                    {
                        Console.WriteLine("mid: {0}, tree길이: {1}",mid,treelist[i].length);
                        sum += treelist[i].length - mid;
                        Console.WriteLine("sum: " + sum);

                    }
                }

                Console.WriteLine("총 sum: "+sum);
                Console.WriteLine();

                if (sum < M)
                {
                    right = mid - 1;
                }
                else if (sum >= M)
                {
                    left = mid + 1;

                    result = mid;
                    
                }
            }

            Console.WriteLine(result);

        }
    }
}

 

 

'C# > 알고리즘' 카테고리의 다른 글

17. 1038번 감소하는 수  (0) 2020.09.06
15. 8980번 택배  (0) 2020.09.05
14. 4963번 섬의 개수  (0) 2020.09.05
13. 1967번 트리의 지름  (0) 2020.07.26
12. 1074번 Z (시간 줄임)  (0) 2020.07.11