Блог пользователя iSlava

Автор iSlava, история, 10 лет назад, По-русски

Встретил задачку:

Есть N (3 ≤ N ≤ 10000) длин отрезков. Нужно выбрать 3 с них так, что бы полученный треугольник имел наименьшую площадь и вывести ее.

Прошу помочь ибо нету никаких идей.

  • Проголосовать: нравится
  • +44
  • Проголосовать: не нравится

»
10 лет назад, # |
  Проголосовать: нравится +16 Проголосовать: не нравится

Если зафиксировать 2 стороны, то синус угла между ними нужно минимизировать, т.е третью сторону минимизировать или максимизировать. То есть нужно попробовать 2 варианта: минимальная сторона больше b — a и максимальная меньше a+b

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    спасибо, но даже при лучшем раскладе выходит O(n^2).

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится +6 Проголосовать: не нравится

      Ну да, квадрат и выходит, если делать 2 указателя.

      У вас же ограничения под квадрат явно

      • »
        »
        »
        »
        10 лет назад, # ^ |
        Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

        Там ТЛ 500мс, и сервер слабенький

        UPD Прошу прощения,все таки ТЛ 2с

        • »
          »
          »
          »
          »
          10 лет назад, # ^ |
            Проголосовать: нравится +5 Проголосовать: не нравится

          Так что, это решение подходит или можно ещё подумать? Учтите ещё, что можно перебирать только один из двух указанных вариантов. А ещё какие длины сторон-то? Если целые и  ≤ k, где k не слишком большое, то можно за O(k + n) найти всевозможные суммы, а потом за O(k + n) же найти для каждой суммы s ближайшую к ней длину отрезка  < s.

          • »
            »
            »
            »
            »
            »
            10 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            Длины отрезков до 20000, и заданы нам квадраты длин отрезков

»
10 лет назад, # |
  Проголосовать: нравится -19 Проголосовать: не нравится

Сначала отсортируем массив по возростанию. Далее перебираем три последовательных числа с помощью for. Если из трех можно составить треугольник выводим эти числа. P.S. Являются ли отрезки треугольником можно проверить с помощью if(a+b>c&&b+c>a&&a+c>b&&abs(a-b)<c&&abs(a-c)<b&&abs(b-c)<a)

»
10 лет назад, # |
Rev. 4   Проголосовать: нравится 0 Проголосовать: не нравится

Если я правильно понял условие, то вот решение за O(n2).

У нас не больше 2N различных точек — концов отрезков. Построим граф: точки — вершины, а ребра — отрезки. Будем хранить в остортированном виде в какую точку мы можем попасть из текущей.

Переберем отрезок. У нас уже есть 2 точки треугольника, нужно определить третью. Для этого объединим, в какую третью точку мы можем попасть и из первой, и из второй одновременно (слить два отсортированных списка). Получили списочек треугольков, которые мы можем получить исспользуя 2 текущие точки (точки от выбранного отрезка) и еще третью (из слитых списков). Итого O(n2), только не ясно, тут квадрат подойдет или надо быстрее.

UPD: То, что я написал, разве не работает за линию? Ведь количество ребер у нас O(n), тогда в сумме сливание списков будет линейное же?

  • »
    »
    10 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    прошу прощения, я не объяснил, даны не точки,а длины отрезков.Виноват

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

вот та же задача, но уже с ограничением n <= 1e5: http://acmp.ru/index.asp?main=task&id_task=594

у меня зашло решение, которое ищет ответ только среди 150 самых длинных отрезков, но это вроде неправда

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    там максимальная площадь,а если я не ошибаюсь она максимальна если брать соседние стороны

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Извиняюсь, не увидел, что минимальная площадь нужна

»
10 лет назад, # |
Rev. 2   Проголосовать: нравится +1 Проголосовать: не нравится

Допустим мы отсортируем все длины отрезков. Не будут тогда нужные нам треугольники вида i, j, j + 1, где i < j?

Допустим стороны нашего треугольника имеют индексы i, j, k и i < j < k. Допустим i и k зафиксированны, тогда очевидно, что j должно быть как можно больше (чтобы высота была как можно меньше у треугольника, за основание отрезок k возьмем). Получается, что при заданных i и k и условии i < j < k либо a[i], a[j = k - 1], a[k] треугольник с минимальной площадью при фиксированных i и k (если правило треугольника соблюдается), либо такого нет.

Если так то, можно просто перебирать j, брать две стороны a[j], a[j + 1] и искать такое минимальное i, что a[i] > a[j + 1] - a[j].

  • »
    »
    10 лет назад, # ^ |
      Проголосовать: нравится +26 Проголосовать: не нравится

    Тест: 5 7 9 10

    5 7 10 даёт площадь лучше, чем 5 9 10

  • »
    »
    10 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится +13 Проголосовать: не нравится

    "очевидно, что j должно быть как можно больше"

    Быть может, все-таки "как можно меньше"?

    • »
      »
      »
      10 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Да, так и есть: как можно меньше и чтобы выполнялось неравенство треугольника. Выше HellKitsune тест, собственно, предоставил, которой показывает, что мое изначальное утверждение не корректно.

»
10 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

https://www.dropbox.com/s/ljywzxkwf11gx75/Sbornik_2010.pdf?dl=0

Надеюсь страница 100 поможет в решении.

»
10 лет назад, # |
Rev. 3   Проголосовать: нравится +16 Проголосовать: не нравится

Пусть вырожденный треугольник по условию подходит. То есть, если есть такие i, j, k : a[i] + a[j] = a[k], нужно их уметь искать. Это аналог задачи 3-SUM. Задача эта хорошо изучена, быстрее чем за Θ(n2) её решать не умеют.

А лучшее по константе решение за Θ(n2) -- как раз описанный в первом посте метод двух указателей.

Кстати, на современных серваках 109 простых операций заходят за секунду. 108 зайдёт даже за 0.5 даже на очень слабом сервере.

UPD: 3-SUM при ограниченных числах решается через быстрое умножение многочленов. Если числа целые от 1 до C, для решения исходной задачи нам достаточно насчитать для каждой суммы двух сторон a+b, f[a+b] = max(b-a). После этого задача решится за O(C).