티스토리 뷰

반응형

이걸 보고 어떻게 이분 탐색이라는 생각을 해내고 이분 탐색이라는 것을 여기에 어떻게 적용하지?? 에 대한 생각이 많았던 문제. 결국 참고 문헌을 봤다.
내가 보기에 이분 탐색이라는 것은 결국
전체에 주어지는 제한 조건수 제한 조건 이라는 키워드와
범위가 있음을 생각을 해야하는 것 같은데, 거기까지의 발상이 안된다. 구간 나누기 문제들을 좀 더 풀어야겠다.

문제

N개의 수로 이루어진 1차원 배열이 있다. 이 배열을 M개 이하의 구간으로 나누어서 구간의 점수의 최댓값을 최소로 하려고 한다. 구간은 다음과 같은 조건을 만족해야 한다.

  1. 하나의 구간은 하나 이상의 연속된 수들로 이루어져 있다.
  2. 배열의 각 수는 모두 하나의 구간에 포함되어 있어야 한다.

구간의 점수란 구간에 속한 수의 최댓값과 최솟값의 차이이다.

예를 들어, 배열이 [1, 5, 4, 6, 2, 1, 3, 7] 이고, M = 3인 경우가 있다.

이때, [1, 5], [4, 6, 2], [1, 3, 7]로 구간을 나누면 각 구간의 점수는 4, 4, 6점이 된다. 이때, 최댓값은 6점이다.

만약, [1, 5, 4], [6, 2, 1], [3, 7]로 구간을 나누었다면, 각 구간의 점수는 4, 5, 4점이 되고, 이때 최댓값은 5점이 된다.

두 경우 중에서 최댓값이 최소인 것은 5점인 것이고, 5점보다 최댓값을 작게 만드는 방법은 없다.

배열과 M이 주어졌을 때, 구간의 점수의 최댓값의 최솟값을 구하는 프로그램을 작성하시오.

입력

첫째 줄에 배열의 크기 N과 M이 주어진다. (1 ≤ N ≤ 5,000, 1 ≤ M ≤ N)

둘째 줄에 배열에 들어있는 수가 순서대로 주어진다. 배열에 들어있는 수는 1보다 크거나 같고, 10,000보다 작거나 같은 자연수이다.

출력

첫째 줄에 구간의 점수의 최댓값의 최솟값을 출력한다.

 

구현

import collections
import copy
import sys

sys.setrecursionlimit(10 ** 4)
input = sys.stdin.readline


# print = sys.stdout.write


def iinput(): return int(input())


def lisinput(): return list(map(int, input().split()))


def dq(a):
    return collections.deque(a)


def minput(): return map(int, input().split())


def liinput(): return list(map(int, list(input().replace("\n", ""))))


def addNode(a, b):
    return [a[0] + b[0], a[1] + b[1]]


def returnValue(graph, node):
    return graph[node[0]][node[1]]


def transpose(graph):
    return list(map(list, zip(*graph)))


if __name__ == '__main__':
    n, m = minput()
    asss = lisinput()
    low = 0
    high = max(asss)
    mid = (low + high) // 2
    answer = max(asss) - min(asss)
    historyList = []
    while low < high and (low, high) not in historyList:
        historyList.append((low, high))
        mid = (low + high) // 2
        copyAss = copy.deepcopy(asss)
        mini = copyAss.pop()
        maxi = mini
        mAllow = 0  # 구간의 개수
        while copyAss and mAllow <= m:
            travel = copyAss.pop()
            mini = min(travel, mini)
            maxi = max(travel, maxi)
            if maxi - mini > mid:
                mAllow += 1
                mini = travel
                maxi = travel
        if mAllow >= m:
            low = mid

            continue
        else:
            high = mid
            answer = min(mid, answer)
            continue
    # mid = (low + high) // 2
    # answer = min(mid, answer)
    print(str(answer))
반응형
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
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
글 보관함