Відвідування пунктів на рядку з цифрами при мінімізації витрат, не пов'язаних з відстані


18

Мені потрібна допомога щодо цієї проблеми ACM ICPC. Моя нинішня ідея полягає в тому, щоб моделювати це як найкоротшу проблему шляху, яка описана в постановці проблеми.

Проблема

Є N = 1000контейнери для ядерних відходів, розташовані уздовж 1-D рядки номера на різних місцях -500,000 to 500,000, крім x=0. Людині доручено зібрати всі відходи для сміття. Щосекунди, коли контейнер для сміття не збирається, він випромінює 1 одиницю випромінювання. Людина починає x = 0і може переміщувати 1одиницю щосекунди, а збирання відходів займає незначну кількість часу. Ми хочемо знайти мінімальну кількість випромінювання, що виділяється під час збору всіх контейнерів.

Зразок введення:

4Контейнери, розташовані в [-12, -2, 3, 7].

Найкращим замовленням для збору цих контейнерів є [-2, 3, 7, -12]мінімальне викидання 50одиниць. Пояснення: людина йде -2за 2 секунди і за цей час 2 unitsвипромінювання випромінюється. Потім він іде до 3(відстань 5:), щоб бочка випустила 2 + 5 = 7одиниці випромінювання. Йому потрібно 4більше секунд, щоб дістатися туди, x = 7де ця бочка викинула 2 + 5 + 4 = 11одиниці. Йому потрібні 19секунди, щоб дістатися туди, x = -12де ця бочка викинула 2 + 5 + 4 + 19 = 30одиниці. 2 + 7 + 11 + 30 = 50, що є відповіддю.

Примітки

Є очевидне O(N!)рішення. Однак я досліджував жадібні методи, такі як перехід до найближчого або перехід до найближчого кластеру, але ті не спрацювали.

Я досить довго думав над цією проблемою і моделював її як проблему пошуку графіків:

  1. Вставляємо 0як базову позицію (Це буде початковий стан)
  2. Потім ми сортуємо позиції від найменших до найбільших.
  3. Потім ми робимо BFS / PFS, де stateскладається з
    • Два цілих числа , lі rякі представляють собою безперервний діапазон в відсортованому масиві позиції , які ми відвідали вже
    • Ціле число, locяке вказує нам, що ми знаходимося в лівій або правій кінцевій точці діапазону
    • Ціле число, timeяке повідомляє нам пройдений час
    • Ціла "вартість", яка повідомляє нам загальну вартість до цього часу (виходячи з вузлів, які ми відвідали)
  4. З кожного стану ми можемо перейти до [l - 1, r] і [l, r + 1], змінивши відповідно 3 інших цілих числа
  5. Остаточний стан дорівнює [0, N], перевіряючи обидві кінцеві позиції.

Однак, здається, що стан [L, R, loc]не визначає однозначно, і нам потрібно зберігати L, R, loc, and time, мінімізуючи costпри цьому кожен із них. Це призводить до експоненціального алгоритму, який все ще занадто повільний для будь-якого блага.

Чи може хтось допомогти мені розширити свою ідею або підштовхнути її в правильному напрямку?

Редагувати: Можливо, це можна моделювати як проблему оптимізації динамічного програмування? Думаючи про це, у нього є ті ж самі проблеми, що і рішення пошуку графіків - тільки тому, що поточний costнизький рівень не означає, що це оптимальна відповідь на цю підзадачу, оскільки це timeтакож сильно впливає на відповідь.

Жадібний не працює: у мене є жадібний алгоритм вибору, який оцінює вартість переїзду до певного місця (наприклад, якщо ми рухаємось праворуч, ми подвоюємо відстані до лівої бочки тощо).

Не могли б ви здійснити пошук за першочерговим завданням з евристикою? Евристика може поєднувати вартість поточної поїздки з кількістю пройденого часу.


Як щодо найкоротших алгоритмів шляху? Як алгоритм Дейкстри?
suraj_fale

Я спробував це, але думаю, що роблю щось справді неправильно. Я описав свій алгоритм (який був першочерговим першим пошуком або BFS) внизу, з нумерованим списком.
Barron W.

Це може допомогти вам ... stackoverflow.com/q/14639346/585398
suraj_fale

Вибачте, я не бачу, як пов’язані ці дві проблеми. Ти можеш пояснити?
Barron W.

2
Це проблема практики ACM ICPC, а не реальна життєва проблема. З іншого приводу, я намагався зменшити стан, але безрезультатно. Я спробував написати рішення щодо DP, але це теж не вийшло. Держава була L, R, POS.
Barron W.

Відповіді:


4

Я думаю, ви можете покращити це, розглядаючи проблему як спрямований графік пар позицій.

Для цього прикладу я буду використовувати рядок зі значеннями -9, -6, -1, 3 і 5.

Оскільки складно намалювати графік просто текстом, я буду представляти пари як таблицю. Ми можемо вважати, що клітини представляють стан, у якому зібрані всі контейнери між цими двома позиціями. Кожна комірка має два значення, одне з яких представляє вартість, щоб перейти ліворуч, а інше - вартість, щоб повернутися праворуч (до наступного контейнера).

Значення можна просто обчислити як відстань між двома точками, помножене на кількість бочок поза цими двома точками + 1 . Клітини, де обидва числа мають однаковий знак, представляють випадки, коли зібрані всі бочки протилежного знака. Вони розраховуються, використовуючи лише кількість бочок у напрямку від нуля.

У таблиці значення X означають, що ви не можете піти в цьому напрямку (усі бочки в цьому напрямку були взяті). Рядки представляють поточне положення колектора, а стовпці - місце розташування наступного протилежного стовбура.

    +------+------+------+------+------+
    |  -9  |  -6  |  -1  |   3  |   5  |
+---+------+------+------+------+------+
|-9 |      |      |      | X, 24| X, 14|
+---+------+------+------+------+------+
|-6 | 3, X |      |      | 9, 27| 6, 22|
+---+------+------+------+------+------+
|-1 |      |10, X |      |20, 8 |15, 18|
+---+------+------+------+------+------+
| 3 |24, 4 |27, 6 |16, 8 |      | X, 2 |
+---+------+------+------+------+------+
| 5 |14, X |22, X |18, X |      |      |
+---+------+------+------+------+------+

Правила переміщення між квадратами можуть бути дещо заплутаними.

Для стовпців з негативними нумераціями правила такі:

  • Якщо рухатись праворуч, рухається вниз по одній клітині.
  • Переходячи вліво, рухається вниз по одній комірці, а потім дзеркалами по діагоналі.
  • Якщо правильне значення X, перехід ліворуч рухається до діагоналі (стовпчик і рядок рівні) і ліворуч на одиницю.

Для позитивних нумерованих стовпців правила такі:

  • Переходячи вліво, рухається вгору на одну клітинку.
  • Праворуч рухається вгору на одну клітинку, а потім дзеркала по діагоналі.
  • Якщо ліве значення дорівнює X, праворуч рухається вниз по діагоналі і праворуч на одну.

Тепер ми можемо запустити алгоритм Діккстра для обчислення найкращого шляху, використовуючи ці правила руху для обходу графіка. Наші вихідні позиції (-1, 3) та (3, -1) з початковими витратами відповідно 5 та 15. Після того як ми обчислили значення для двох кінцевих позицій (зліва від (-9, -9) і праворуч від (5, 5)), менша з двох - це наша відповідь.

Час виконання кожного кроку:

  • O (N log N) для початкового сортування вхідних значень по лінії
  • O (N ^ 2) для обчислення таблиці / графіка
  • O (N ^ 2 log N) для запуску Dijkstra's на графіку (Примітка: для будь-якої вершини є щонайбільше два ребра).

Перші два кроки домінують над останнім, тому загальний час роботи - це O (N ^ 2 log N), що має бути достатньо хорошим для виконання завдання.


1

Найкоротша відстань

Вчора я написав програму Java для вирішення проблеми. Проблема - це проблема найменшої відстані, як це сказав у своєму коментарі SRJ. Випромінювання просто показує, що ви можете накопичити значення разом з найменшою відстані.

В основному, ось що я зробив.

  • Помістіть номери контейнерів у Список <Integer>
  • Поки Список містить елементи;
    • Знайдіть найближчі елементи (елементи)
    • Якщо є один елемент, пройдіться туди і вийміть елемент.
    • Якщо є два елементи, скопіюйте шлях і перейдіть до обох елементів
  • Знайдіть шлях з найменшим значенням випромінювання.

Ось деякий вихід із програми

10 containers are located at [-90, -75, -47, -9, 9, 26, 48, 50, 64, 79].

You walk to position -9 and pick up the container.  The total radiation emitted is 90 units.
You walk to position 9 and pick up the container.  The total radiation emitted is 252 units.
You walk to position 26 and pick up the container.  The total radiation emitted is 388 units.
You walk to position 48 and pick up the container.  The total radiation emitted is 542 units.
You walk to position 50 and pick up the container.  The total radiation emitted is 554 units.
You walk to position 64 and pick up the container.  The total radiation emitted is 624 units.
You walk to position 79 and pick up the container.  The total radiation emitted is 684 units.
You walk to position -47 and pick up the container.  The total radiation emitted is 1,062 units.
You walk to position -75 and pick up the container.  The total radiation emitted is 1,118 units.
You walk to position -90 and pick up the container.  The total radiation emitted is 1,133 units.

Я ні в якому разі не оптимізував алгоритм. Я навіть не помітив, що список вхідних чисел був відсортований. (Я дуф.)

Коли я запустив свій код з максимальними значеннями, 1000 контейнерів і діапазоном від -500 000 до 500 000, на виконання коду знадобилося 3 секунди. Більшу частину цього часу писав на консоль 1000 ліній друку.

Я не велика людина O, але я вважаю, що моя груба сила, що рухається алгоритмом найкоротшого шляху, - це O (N квадрат), а не O (N!).

Якби я скористався тим, що введені числа впорядковані, так що мені довелося лише перевірити два числа з того боку, де я зараз перебуваю, я міг би змусити програму впритул до O (N). Мені потрібно лише перевірити 2 числа, оскільки я видаляю елементи зі Списку, коли я дістаюсь до них.

Ви використовували різні алгоритми, як жадібний алгоритм, щоб знайти приблизне рішення.

Якби для моєї програми було потрібно 3 години, а не 3 секунди, тоді вам доведеться зробити вибір.

Чи достатньо гарне рішення?

Іншими словами, чи готовий я торгувати швидкістю обробки для отримання достатньо гарної відповіді?

Якщо відповідь достатньо хороша, то ви використовуєте алгоритми наближення.

Якщо ви хочете досконалої відповіді, вам доведеться пройти всі найкоротші шляхи. Немає ярлика.

Якщо хто хоче, щоб я опублікував свій код, я зроблю. Я впевнений, що все ще є помилки, тому що я хотів побачити, чи можу я реалізувати алгоритм найкоротшого прогулянки.


1

У мене є рішення, яке 2^Nвчасно вирішить цю проблему , але це погано, але я вважаю, що це корисний спосіб вирішення проблеми, тому я подумав, що буду опублікувати.

Замість того, щоб моделювати задачу як графік, я б моделював це бінарне дерево рішень (скажімо T). На кожному рівні вам потрібно вибрати між правильним або лівим. Вирахувати «вартість» кожного краю досить просто. Нехай h(K)буде висота поточного вузла K, тоді вартість краю збирається left_child(K) = h(K) x dist(K, left_child(K)). Аналогічного розрахунку достатньо для вартості краю правильній дитині. Ви будуєте це дерево і стежите за накопичувальною вартістю країв увесь шлях вниз і повідомляєте про шлях до вузла листя з найменшими загальними витратами.

Зауважте, що калькуляція витрат працює, тому що довжина кожного краю dist(K, left_child(K))представляє час для переходу до наступного майданчика, тоді як висота піддерева - кількість сайтів, що залишилися (наприклад, все ще випромінюють радіацію).

Тепер фокус у цих рамках полягає в тому, щоб визначити, чи є евристика, яку ви можете використати, щоб «довести», що ви можете ігнорувати розширення пошуку вздовж якоїсь гілки. Моя інтуїція полягає в тому, що для будь-якої такої евристики існує розташування сайтів, які переможуть її, але, можливо, хтось може щось придумати.

Ряд запропонував застосувати для графіків найкоротші шляхові рішення, у мене є сумніви щодо того, чи може таке рішення спрацювати. Ваші сусіди в 'графіку' проблеми змінюватимуться залежно від шляху, який ви слідуєте. Наприклад , у вихідному повідомленні з , [-12, -2, 3, 7]якщо ви йдете на -2те -12і 3стаєте «сусідами» , і якщо ви йдете , 3то -2і 7сусіди. Кожна можлива «пара» позитивних і негативних значень потенційно може бути неоднозначною в кінцевому графіку. Я не знаю жодних алгоритмів найкоротшого шляху, які в динамічному графіку виявляються правильними.


0

Я думаю, що має сенс розглядати кожен етап просто як двійковий вибір між прямим правом до найближчої бочки та виїздом ліворуч до найближчої бочки. Просто є функція витрат, яка детально визначає кількість одиниць випромінювання, яка б була здійснена в цілому, зробивши будь-який рух і виберіть той, з найменшими витратами.

НЕ просто розглядайте найближчу бочку, а замість цього припускайте, що, віддаляючись від бочки, ви ефективно додаєте вдвічі випромінювання, оскільки, віддаляючись, ви також понесли витрати на те, щоб пізніше повернутись у цьому напрямку.

У вашому прикладі [-12, -2,3,7], якщо рухатись ліворуч, то вліво буде 14 (2 + 2 + 10) зліва, а 18 (2 + 2 + 5 + 9) праворуч, в цілому 22. Якщо рухатись праворуч, 10 (3 + 3 + 4) праворуч і 26 (3 + 3 + 5 + 15) праворуч. Ясно ліворуч - спочатку правильне рішення. Аналогічний розрахунок можна зробити для кожного наступного руху.

Після цього проблема в основному зводиться до пошуку, тому складність повинна бути O (nlog (n)), що набагато краще, ніж O (n!). Я вважаю, що це обов'язково найнижча складність, яка може існувати для цієї проблеми, оскільки це в основному алгоритм пошуку на основі порівняння, для якого не можна зробити краще, ніж O (nlog (n))

Мабуть, мені було недостатньо зрозуміло з цим описом, тож я вирішив зробити його трохи більш програмним: 1. Обчисліть витрати, понесені ліворуч, та витрати, понесені правим, виходячи з поточної позиції. 2. Перемістіть найменш дорогий напрям 3. Видаліть досягнуту бочку з розгляду при обчисленні вартості руху в напрямку

Розрахунок вартості: 1. Визначте найближчий стовбур у заданому напрямку. Скажімо, що $ dist - це відстань від поточного положення до найближчої бочки у заданому напрямку. 2. Вартість ініціалізується як N * $ dist, де N вважає лише активні барелі. 3. До цього додайте відстань, яку нове положення, вказане $ dist, буде від кожного залишився бареля.


1
Це не завжди працює. Можливо, ви могли б сортувати координати, а потім здійснити пошук там, де стан містить діапазон [i..j] (який означає, який діапазон ви відвідали) та вартість та поточний час.
Barron W.

Коли це не працює?
Слейтер Вікторофф

Був простий тестовий випадок, коли це не вдалося. Я спробую його знайти, але це було з N = 4 або 5.
Barron W.

[43, -18, -98, -82, 63]
Barron W.

Також такі випадки [-10,-11, 10,20,30,40,50,60,70]. Правильне і єдине рішення - зібрати всі негативні, потім зібрати позитивні. Для відповіді 455.
Barron W.

0

Часткове рішення - я повернусь до нього пізніше.

Припустимо, що стратегія "за замовчуванням" виконується вліво або вправо, залежно від того, що дешевше. А тепер запитайте, чи варто трохи поїхати в інший спосіб, щоб забрати одну бочку. Вирахувати відповідь досить просто.

Для вашої вибірки введення, біг по дорозі вправо дешевше, ніж увесь шлях вліво. Збираєтесь до -2 варто поїздкою? Це знижує вартість роботи в повному обсязі, а потім повернеться до 0 на 14 (тому що ви "платили" 4 одиниці радіації за хід від 0 до 3 за стратегією за замовчуванням, тепер вона знижена до 3, ви платили 3 з 3 до 7, зараз це 2 і т. д.), плюс зменшує на один хід ваші витрати на переміщення від 0 до -2, таким чином заощаджуючи ще 2 на загальну суму 16.

Однак це додає вартість переходу до -2, а потім назад до 0 з 14 (4 одиниці за хід до -2, 3 за хід назад до 0), для чистого прибутку (16-14) = 2. Зауважте, що для того, щоб обчислити це, вам не потрібно оцінювати точну вартість вирішення всієї проблеми для кожного рішення - у вас є достатня кількість інформації, щоб вирішити, знаючи, чи бігати вліво вліво дешевше, ніж бігати вправо, плюс як багато контейнерів для сміття знаходиться з кожної сторони від вас, а відстань до найближчого 2. Отже, це O (N ^ 2).

За винятком однієї важливої ​​проблеми - я припускав, що ви будете бігати до кінця, і ми знаємо, що ви можете подвоїтися. Щоб очистити це, нам потрібно оновити мій розрахунок. Щодо введення зразка, я припускаю, що ви заощадите 14, випромінюючи на 1 менше загального випромінювання за одиницю в секунду, працюючи від 0 до 7 і назад. Але якщо подвоїтись назад до запуску до 7, заощадження будуть зменшені.

Це досить погано, тому що я не знаю, як обчислити наступний подвійний зворот, не намагаючись усі можливості, що повертає нас до O (2 ^ N).

За винятком - це 2 ^ N з обрізками. Я підрахував, що "бічна поїздка" до -2 коштувала 14, але здобула 16, якщо у мене не було більше побічних поїздок, перш ніж я здійснив її до кращого числа. Якби найправіше число було 5, я б одразу знав, що бічна поїздка до -2 не могла б окупитися. (Вартість ще 14, максимальна вигода 12). Також я не повинен розглянути можливість поїхати до -2, а потім здійснити похід в сторону, перш ніж досягти 6, оскільки це завжди поступається тому, щоб перейти прямо до цієї точки в першу чергу.


0

Я думаю, що ви можете вирішити це за допомогою першого пошуку в ширині, зберігаючи не більше 2 * N ^ 2 кортезів (boolean, int, int, int, string) там, де рядки до тих пір, поки шлях складний.

Кортежі - це (min або max boolean, min пройдене положення, max пройдене положення, загальне випромінювання, історія шляху).

Я бачу алгоритм так:

  1. Ініціалізуйте пул кортежів до одного запису, (хв, 0, 0, 0, "")
  2. Знайдіть у басейні елемент, який має мінімальне випромінювання. Якщо min і max відповідають min і max всіх бочок, то історія шляху є оптимальним рішенням. В іншому випадку видаліть його з пулу.
  3. Обчисліть 2 нащадки цього кортежу, кожен з яких відповідає ходьбі вліво або вправо до наступної необробленої бочки.
  4. Вставте нащадків у басейн. Якщо в пулі вже є елемент із таким же булевим, min та max, як новий нащадок, відмовтеся від елемента з більшим числом радіації.
  5. goto 2.

Пошук та видалення домінуючих кортежів значно покращить продуктивність. Можливо, варто додати прапор "розводив" до кожного кортежу і залишити розведені кортежі в басейні.

Існує також кілька важливих рішень, які слід прийняти, вирішуючи, як зберігати кортежі та шукати в них панування та нові елементи для розмноження.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.