Wyzwanie
N miast jest wyrównanych w linii prostej. I-te miasto znajduje się A[i]
kilometry na prawo od miejsca pochodzenia. Żadne dwa miasta nie będą w tym samym miejscu.
Zamierzasz zbudować sieć elektryczną z kilkoma elektrowniami. Elektrownie muszą być budowane w mieście. Możesz budować tylko K
elektrownie (<N), więc będą miasta, w których nie będzie elektrowni. Dla każdego miasta bez elektrowni musisz zbudować kabel między nim a najbliższym miastem, które ma elektrownię .
Na przykład, jeśli są zlokalizowane trzy miasta 0, 1, 2
, a tylko miasto 0
ma elektrownię, musisz zbudować dwa kable, jeden od 2
do 0
(2 km), a drugi od 1
do0
(1 km) o łącznej długości 3 km .
Dane K
i pozycje miast (A
), należy obliczyć minimalną liczbę kilometrów kabla potrzebną do zbudowania sieci.
Przykładowe przypadki testowe
K = 1, A = [0, 2, 4, 6, 8] : 12
# build power plant in the city at position 4, total length = 4 + 2 + 0 + 2 + 4 = 12
K = 3, A = [0, 1, 10, 11, 20, 21, 22, 30, 32] : 23
# build power plants in cities at positions 0, 10 and 22
K = 5, A = [0, 1, 3, 6, 8, 11, 14] : 3
# build power plants in all cities except those at positions 0, 3
K = 6, A = [0, 1, 3, 6, 8, 14, 15, 18, 29, 30, 38, 41, 45, 46, 49, 58, 66, 72, 83, 84] : 49
Dane techniczne
Powinieneś zaimplementować funkcję lub program, który przyjmuje dodatnią liczbę całkowitą
K
i listę liczb całkowitychA
w dowolnej formie, i wypisuje / zwraca liczbę całkowitą reprezentującą odpowiedź.A
jest posortowane w porządku rosnącym, a wszystkie elementy są liczbami całkowitymi nieujemnymi.A[0] = 0
, iA[N-1]
będzie nie więcej niż 1000 N.Zauważ, że moc wyjściowa będzie wynosić 1000 N 2 , więc w większych przypadkach możesz potrzebować 64-bitowych liczb całkowitych w niektórych językach.
Wielowątkowość nie jest dozwolona ( ustawię powinowactwo twojego programu na 1 rdzeń podczas oceniania).
-O2
Dozwolone są optymalizacje kompilatora (takie jak w C).
Punktacja
Wyznaczę czas twojego kodu na moim komputerze (Ubuntu 16.04 z procesorem Intel i7-3770S) z różnymi rozmiarami przypadków testowych. W szczególności wygeneruję kilka przypadków testowych z N = floor (2 x / 5 ), gdzie x jest dodatnią liczbą całkowitą.
Twój wynik będzie wartością x najmniejszej próbki testowej, którą Twój program używa dłużej niż 10 sekund lub 1 GiB pamięci lub nie daje poprawnej odpowiedzi.- Odpowiedź z najwyższym wynikiem wygrywa. Jeśli dwie odpowiedzi otrzymają ten sam wynik, wygrywa wcześniejsza odpowiedź.
Wszystkie programy będą oceniane według tego samego zestawu przypadków testowych.
Możesz dodawać własne wyniki. Zachęcamy do objaśnienia twojego algorytmu.
Premia
To mój program w C ++, który ma 108 punktów . Możesz zweryfikować skrót SHA-256 9a87fa183bad1e3a83d2df326682598796a216b3a4262c32f71dfb06df12935d
przez cały segment kodu (bez stopki) w łączu.
Algorytm łączy wyszukiwanie binarne i optymalizację Knutha, aby znaleźć właściwą karę dla każdej rośliny i uzyskać żądaną liczbę. Złożoność wynosi O (N log N log A [N-1]). Byłem zaskoczony, że program uzyskał wyższy wynik niż rozwiązanie O (N log A [N-1]) Andersa Kaseorga . Prawdopodobnie wynika to z faktu, że przypadek dziennika w optymalizacji Knutha zwykle nie występuje.
Pamiętaj, że to wyzwanie jest takie samo jak w przypadku urzędu pocztowego IOI 2000 . Jednak pierwotne ograniczenia to N <= 300 i K <= 30.
źródło
2^^(x/5)
: jakie jest znaczenie ? czy możesz podać górną granicę dla N?N=21( = floor(2^(22/5)) )
w ciągu 10 sekund, ale nie poradzi sobieN=24( = floor(2^(23/5)) )
, wynik będzie równy 23. Nie użyłem górnej granicy, ponieważ różnice między różnymi algorytmami są zbyt duże. Na przykład, jeśli zestaw n <= 40, będzie mała różnica międzyO(KN^2)
aO(KN^3)
, więcO(2^N)
nie będzie jeszcze zakończyć w rozsądnych czasu.Odpowiedzi:
Rdza , wynik = 104
Jest to implementacja algorytmu zauważonego przez Grønlund i in. (2017) na końcu §3.3.1, chociaż musiałem przestrzegać długiego łańcucha cytowań i uzupełnić brakujące dane. Działa w czasie O ( N log A [ N - 1]).
Kompiluj z
rustc -O
. Format wejściowy znajdujeK
się w pierwszym wierszu, po nim wpisyA
, jeden wpis w wierszu, wszystkie na standardowym wejściu.(Uwaga: przesyłam to godzinę po terminie nagród, ale spodziewam się, że ostatnia wersja, którą przesłałem przed upływem terminu nagród , który upłynął w czasie O ( N log N log A [ N - 1]), uzyskała około 94 .)
Wypróbuj online!
Rdza , wynik testu wstępnego = 73
Kompiluj z
rustc -O
. Format wejściowy znajdujeK
się w pierwszym wierszu, po nim wpisyA
, jeden wpis w wierszu, wszystkie na standardowym wejściu.Wypróbuj online!
źródło
61
, ale to z powodu przepełnieniau32
. Może możesz zmienić na 64-bitową liczbę całkowitą?type Cost = u32
natype Cost = u64
?73
.C, wynik = 56
zawartość
a.c
:skrypt powłoki, aby skompilować i przetestować powyższe:
n = 776 zajmuje 6,2 s, n = 891 trwa 12 sn = 1176 zajmuje 5,9 s, n = 1351 zajmuje nieco ponad 10 sn = 1351 zajmuje 8,7 s, n = 1552 zajmuje więcej niż 10 s (przy k = 2 * n / 3) na moim
Intel(R) Core(TM) i3-2375M CPU @ 1.50GHz
źródło
syntax/c.vim
.C ++, wynik = 53
Rozwiązanie, które powiedziałem w komentarzu.
O(n²×k)
. (teraz go usunąłem, ponieważ nie jest już potrzebny) Prawdopodobnie można go zmniejszyć doO(n×k)
.Dane wejściowe są dość elastyczne, w pierwszym wierszu pierwsza liczba jest
k
, pozostałe liczby są elementami tablicya
, ale jeśli napotka jakieś nawiasy, przestaje czytać dane wejściowe. Tak więc wejście podobneK = 1, A = [0, 2, 4, 6, 8] : 12
jest akceptowane.Wypróbuj online!
Generuj losowe przypadki testowe. ( domyślnie podaj
N
i opcjonalnie zasięg miasta1000×N
)źródło
int
s naint64_t
s.C #, wynik = 23
Jestem pewien, że to nie wygra tego wyzwania, chciałem tylko opublikować pierwszą (i bardzo podstawową) odpowiedź, aby zachęcić inne osoby do opublikowania swoich algorytmów i ulepszenia mojego. Ten kod musi zostać skompilowany jako projekt konsoli korzystający z pakietu Combinatorics firmy NuGet. Główna metoda zawiera niektóre wywołania
Build
metody do testowania proponowanych przypadków.Naprawdę proste wyjaśnienie: dla każdej kombinacji
c
zk
elementami za
oblicz sumę odległości od każdego elementua
z dokładnością do elementuc
i przywrócić połączenie z najmniejszą łączną odległość.Jednowierszowa wersja
Build
metody (prawdopodobnie wolniejsza niż oryginalna, rozszerzona wersja; należy do niej dodać odniesienieSystem.Linq
):źródło
C ++, wynik = 48
Dane wejściowe użycia: NKA [1] A [2] ... A [N]
źródło
step
do 70, twój wynik w teście wstępnym to 60.Rubin , wynik = 23
Wypróbuj online!
Nie sądzę, że wygra, ale chciałem spróbować.
źródło
JavaScript (ES6) (Node.js) , wynik = 10
Nowy algorytm wyjaśni, czy tym razem faktycznie działa.
Wypróbuj online!
Uruchom taki sam sposób jak drugi.
JavaScript (ES6) (Node.js) , wynik testu wstępnego = 12
Zarys algorytmu:
Najpierw program mapuje dane do klasy miasta, która mapuje kilka punktów danych:
tablica jest następnie wrzucana do klasy Group, która ma następujące cechy:
Teraz algorytm dzieli grupy, o ile ma 2 lub więcej elektrowni do umieszczenia.
Na koniec mapuje grupy do centrów i sumuje je wszystkie.
Jak uruchomić:
Uruchom za pomocą Node.js (wersja 9.0.0 została użyta do stworzenia)
uruchomienie programu przy użyciu wygenerowanych przypadków testowych dla wyniku 70:
uruchomienie programu z wykorzystaniem 1 elektrowni i miast [0,3,5]:
Kod:
Wypróbuj online!
Wyczyszczę skomentowany kod w ciągu najbliższych kilku dni, ponieważ wciąż nad tym pracuję, chciałem tylko sprawdzić, czy to przechodzi więcej niż tylko małe skrzynki.
źródło
K = 2, A = [0, 21, 31, 45, 49, 54]
. Prawidłowa odpowiedź to 40, ale program generuje wynik 51.K = 2, A = [0, 4, 7, 9, 10]
. Prawidłowo: 7, twoja odpowiedź: 8.K = 2, A = [0, 1, 3, 4, 9]
. Poprawnie: 6, twoja odpowiedź: 7.C (niekonkurencyjny, wynik testu wstępnego = 76)
Jest to próba przetłumaczenia drugiego rozwiązania Rust @ AndersKaseorga na język C.
Połącz z:
źródło
Czyste , wynik = 65
Połącz z:
clm -h 1024M -gci 32M -gcf 32 -s 32M -t -nci -ou -fusion -dynamics -IL Platform main
Pobiera
K
, a następnie każdy elementA
jako argumenty wiersza polecenia.źródło