4 / 11
May 2017

Witam.
Napisałem rozwiązanie zadania jak w temacie.Zestawy wejściowe liczb wartości i rozmiaru posortowałem malejąco według opłacalności pakowania do plecaków braci a tam gdzie stosunek wartość/rozmiar jest identyczny ( przykład para liczb 3 i 4 oraz 6 i 8 - obie mają stosunek 0,75 ) wyżej w priorytecie sortowania ustawiłem tą gdzie wielkość liczb jest większa ( sprawdzam po zmiennej wartość, ale to chyba bez znaczenia po której sprawdzam? ). Tak ułożone pary liczb wkładam po kolei do plecaków do zapełniania obu i w pierwszym przykładzie mam poprawny wynik czyli:
Wyjście:
16
1 2 4
3 5
Niestety przykład 2 wydaje się działać już według innej logiki, gdyż program działając jak opisałem wyżej dla drugiego zestawu liczb podaje już inny wynik niż przykład.
W przykładzie 2 ze SPOJ program autora zadania ułożył wyżej w kolejności do zapakowania do plecaków parę liczb 4 i 4 ( czyli stosunek proporcji 1 ) niż parę liczb 3 i 2 ( o stosunku wartość / rozmiar 1,5 ). Według wyniku przykładu 1 powinien zachować się odwrotnie ale w przykładzie 2 chyba zadziałał jakiś inny algorytm sortowanie kolejności pakowania ?
Co jest nie tak? Czy trzeba wziąć pod uwagę coś jeszcze? Dodam ze moja metoda za każdym razem pakuje do plecaków taka wartość przedmiotów jak w przykładach czyli sumę zlicza dobrze i zapełnia plecaki do końca jak należy ( przynajmniej w przykładach z zadania) , a jedynie w innej kolejności?
Proszę o wyrozumiałość i cierpliwe wyjaśnienie, gdyż programuje ( w C++ ) dopiero od miesiąca a w dodatku to zadanie to moje pierwsze podejście do kategorii TRUDNE na SPOJ.
Czy autor zadania mógłby dodać więcej przykładów z wynikami aby lepiej zobaczyć jaką logiką sortowania kieruje się program którego oczekuje jego zadanie?
Eryk

  • created

    Apr '17
  • last reply

    Aug '17
  • 10

    replies

  • 1.8k

    views

  • 5

    users

  • 4

    links

Ło ma lamo, ale żeś pokićkał! :wink:

Skąd pomysł, że w tym zadaniu trzeba cokolwiek sortować? Znaczy - nie przeczę, sortowanie może prowadzić do rozwiązania (nie robiłem tego zadania, a na SPOJu jestem raczej nieaktywny o ponad pół roku dłużej niż bym tego chciał). Ale tematem zadania nie jest sortowanie i słowo to nie pojawia się w treści zadania.

Rozpatrzmy przykład pierwszy. Masz sześć przedmiotów o danych wartościach i rozmiarach. Masz rozwiązać problem optymalizacyjny - wartość przedmiotów ma być jak największa. Podane są przy tym dwa ograniczenia - rozmiary obu plecaków. Największą wartość uzyskasz biorąc przedmioty 1, 2 i 4 do pierwszego plecaka i 3 oraz 5 do drugiego. Wówczas pierwszy plecak będzie przechowywał wartość 4+6+2 = 12 i będzie miał masę 1+2+1 = 4. Plecak jest pełny więc pakujemy kolejny: bierzemy przedmiot trzeci i piąty o łącznej wartości 3+1=4 i masie 2+1=3. Plecak jest pełny. Mamy przedmioty o wartości łącznej 12 + 4 = 16. Biorąc przedmioty w inny sposób nie uzyskasz maksymalnej wartości albo przekroczysz dopuszczalne masy.

W drugim przypadku masz 4 przedmioty i plecaki o pojemności 6 i 3. Do pierwszego weźmiesz przedmioty trzeci i czwarty o łącznej wartości 4+3=7 i masie 4+2=6. Pierwszy plecak jest pełny. Do drugiego weźmiesz tylko przedmiot drugi o wartości 2 i masie 2. Masz więc łączną wartość 7+2=9, a drugi plecak nie jest całkowicie zapełniony - inne przedmioty są za duże by je włożyć. Również jest to rozwiązanie prawidłowe. Pakując plecak w inny sposób albo przekroczysz jego pojemności albo uzyskasz mniejszą wartość niż 9.

Wniosek: Twój algorytm jest zły.
Hipoteza/rada: Jeżeli dopiero od miesiąca kodujesz nie tyle w C++ co w ogóle i od niedawna masz styczność z algorytmami (sugeruje to Twój profil na SPOJu) to nie rób zadań trudnych. To zadanie nie jest proste a gdybym miał zgadywać jak je rozwiązać (nie mam czasu nad tym głęboko myśleć) to nie widzę tutaj żadnego sortowania, ewentualnie sortowanie to jakiś trywialny etap rozwiązania dość trudnego problemu algorytmicznego.

Dzięki za odpowiedź. Przyznam że mnie zaskoczyła i nie przyszło mi do głowy że sortowanie tych danych wejściowych może być złą koncepcją rozwiązania tego zadania. Po prostu treść zadania wydała mi się interesująca ( jak by to ujął Mirosław Zelent "seksowna") pomyślałem nad nim chwilę i wpadłem na pomysł jak można by je rozwiązać ( patrząc po rozwiązaniu przykładu 1, analizy przykładu 2 nie zrobiłem na swoje nieszczęście wtedy).
Stwierdziłem że trafia się okazja aby zrobić nowy poziom challenge i ochoczo zabrałem się do pisania. Nie wiedziałem czego się spodziewać po zadaniach w kategorii trudne, ale nawet robiąc i swoją metodą zrobiłem kilka nowych rzeczy nierobionych wcześniej ( sortowanie 4 zbiorów danych na raz po 2 parametrach ) a kod wyszedł obszerniejszy niż przy łatwych i średnich.
Pewnie marna jest szansa żeby któraś ze 159 osób które je rozwiązały mi odpisała tu na ten wątek, ale może Ty albo któryś inny z bardziej doświadczonych kolegów miałby ochotę nad nim posiedzieć i je rozwiązać, wykluczając lub potwierdzając mój pomysł na jego rozwiązanie?


Cóż mogę rzec. Nie rozwiązałem tego zadania więc nie mogę wypowiadać się z pozycji eksperta :wink: Ale jeżeli poszukujesz wskazówek...

Pomysł jest taki. Ja napiszę co widzę w taki sposób w jaki rzeczywiście układa mi się wizja tego zadania w głowie. Bez zbędnych upiększeń, dbałości o gramatykę i liczne przykłady. Być może niewiele zrozumiesz z tej wypowiedzi, ale właśnie o to chodzi :wink: Każdą rzecz której nie rozumiesz możesz wygooglować albo znaleźć w jakiejś książce. Nota bene pewną część tej wizji już znasz z mojego poprzedniego postu. Zauważ też, że nie rozwiązałem tego zadania i być może moje rozumowanie nie jest prawidłowe, co dostrzegłbym (albo i nie) dopiero po wczytaniu się w treść i próbie stworzenia dobrego algorytmu

Wiemy, że SPOJ to tylko i aż SPOJ. Tylko - zadania które tu występują mogą wydawać się piekielnie trudne, ale w rzeczywistości nie wymagają żadnej wielkiej i abstrakcyjnej wiedzy. Aż - wiele osób posiadających wielką i abstrakcyjną wiedzę nie ma szans z wieloma zadaniami średnimi, a pewne problemy mogą im sprawić również zadania łatwe. W gruncie rzeczy SPOJ to kwestia wprawy i oczywiście chęci poświęcenia czasu na jakiś problem :wink: Wniosek - rozwiązania zadania nie należy szukać w najnowszych osiągnięciach matematyki teoretycznej tylko w czymś znanym.

Przedmiotów jest zaledwie 100, a pojemności plecaków to 500. Ogólnie autor operuje bardzo małymi liczbami, a ilość testów jest znana i wynosi 1 - każdy przykład stanowi samodzielny test. Odnotowane fakty nie miałyby znaczenia gdyby nie to, że - jak pisałem w poprzednim akapicie - to jest SPOJ. Na podstawie specyfikacji zadania można oszacować złożoność czasową wzorcówki (rozwiązania wzorcowego). Bierzemy sobie np to http://www-users.mat.umk.pl/~stencel/acm/algorytmika_praktyczna.pdf21 i patrzymy na rozdział 9. Okazuje się, że nasz program z dużą dozą prawdopodobieństwa powinien mieć złożoność O(n^3), co jest bardzo użytecznym wnioskiem!

Jednocześnie w podanej pozycji napisano, że w tej klasie rozwiązań znajdują się zazwyczaj problemy rozwiązywalne metodą programowania dynamicznego. Czy ma to sens? Znowu - wracamy do tego, że SPOJ to SPOJ. Jedną z cech SPOJa jest to, że ma uczyć. Autorzy nie tworzą zadań by pokazać jacy są mądrzy a po to, by pomóc innym ludziom nauczyć się algorytmów i programowania. Z tego powodu nieraz w treści zadania znajduje się jakaś podpowiedź - nazwa algorytmu, aluzja do jakiegoś problemu matematycznego, a nawet nazwa typu zmiennej w jakimś języku programowania, której zastosowanie jest kluczowe w celu rozwiązania. Możesz też spotkać się z fragmentami kodu, które trzeba uzupełnić i innymi tego rodzaju podpowiedziami. Czy w tym zadaniu jest podpowiedź? Tak! Jest nią słowo plecak, które prowadzi do dyskretnego problemu plecakowego, który z kolei jest problemem optymalizacyjnym rozwiązywalnym w czasie O(2^n) brutem (brute force algorithm, algorytm naiwny, algorytm brutalny, podejście brutalne, algorytm siłowy, podejście siłowe, ...), ale metodą programowania dynamicznego można go rozwiązać w czasie wielomianowym O(n^2). Stwierdzenie, że zadanie ma coś wspólnego z plecakami jest bezcennym wnioskiem!

Przerwa od analizy zadania :wink: Jako ciekawostkę mogę Ci powiedzieć, że Twoje podejście było niezłe. Podwójnie niezłe. Po pierwsze, prawidłowo rozwiązałeś / prawie prawidłowo rozwiązałeś (nie mam kodu więc głowy nie dam) pewną szczególną podklasę problemów plecakowych, dla których metoda zachłanna prowadzi do znalezienia optimum. Po drugie, podałeś całkiem dobry algorytm aproksymacyjny dla dużej części innych podklas problemów plecakowych. Wracamy do analizy zadania :wink:

Wiemy, że zadanie stanowi zmodyfikowaną i rozszerzoną wersję problemu plecakowego. W związku z tym należy się zapoznać z tym problemem, przeanalizować go i zaproponować rozwiązanie zadania pamiętając, że najprawdopodobniej autor chciałby solucję o złożoności obliczeniowej około O(n^3). Oczywiście limit czasu wynoszący 10 sekund może sugerować, że w istocie chodzi nawet o jakieś O(n!), O(2^n) itd, ale to wyjdzie w praniu - na pewno nikt nie oczekuje od Ciebie arcyszybkiego programu podającego odpowiedź jeszcze przed wczytaniem danych albo programu, który miliardy przedmiotów zapakuje w odpowiedni sposób w czasie kilku milisekund :wink: Słowem plecaki + programowanie dynamiczne vs zachłanne + wysiłek własny powinny prowadzić albo do AC albo do pomysłu na program, który uzyska AC :wink:

PS
Zauważ, że zadanie na maksa (100.0) rozwiązało dużo mniej osób, bo 55.

Poziom trudne to trudne, poziom chalange, to poziom chalange.

Należało najpierw pomyśleć trochę więcej niż tylko chwilę, poczytać, a dopiero potem zabierać się do pisania.

Radzę z dobrego serca, poszukaj sobie innego autorytetu i źródła wiedzy lub korzystaj z tego wideo-kursu najeżonego błędami ale potem nie mów, że Cię nie ostrzegłem.

Bardzo marna, bo dużo mniej osób uzyskała tu maksa, [niektórzy mogli wysłać po kilka rozwiązań 100 pkt [w różnych językach]. Ja do nich nie należę.

PS
Powinieneś podać link do listy swoich zgłoszeń do tego zadania: http://pl.spoj.com/status/ETI07E7,cyberstormppc/19. Ułatwia to pomagającym pomaganie!.

Miałem ochotę to napisać w nieco bardziej krytyczny sposób, ale się powstrzymałem :wink: Skoro mnie zachęciłeś... Fakt - słuchanie Zelenta może doprowadzić do poważnych trudności nie tylko w znalezieniu zatrudnienia w branży IT (chyba wszystko co Zelent robi/radzi w C++Builder jest tym czego nie wolno robić chcąc tworzyć czytelny kod; w innych odcinkach jest niewiele lepiej), ale też w szeroko rozumianym rozwoju intelektualnym. Mówię to jako człowiek, który od Zelenta zaczął swoją naukę kodowania. Problemy zaczynają się w dalszych odcinkach C++ i z odcinka na odcinek są coraz bardziej poważne. Przemyślenia filozoficzno-matematyczne tego Pana również budzą poważne zastrzeżenia, nie brakuje w nich numerologii i dziwnych interpretacji, a nawet powiedziałbym - zwykłych bredni.

W sumie to przykre, bo kurs zapowiadał się ciekawie i miał potencjał. Niestety oprawa audiowizualna zastąpiła przekaz merytoryczny. W tym jeszcze nie ma nic złego - każdy popełnia błędy, a łatwo skupić się na formie przekazu w takim stopniu, że zapomina się o jego treści. Niestety, autor nie tylko pozostał przy dość nijakim poziomie merytorycznym, ale jeszcze zdaje się być przekonany o swojej nieomylności. Brednie o złotej proporcji są w jego mniemaniu ciekawymi i wartymi przedstawienia faktami, niedociągnięcia w stylu kodowania uważa za konieczne uproszczenia dydaktyczne, beznadziejnie słaby opis struktur danych nie doczekał się żadnej poprawki, a do tego wszędzie pseudofilozoficzny bełkot... słowem odradzam. Sukces autora oparty jest wyłącznie na tym, że wielu ludzi chciałoby się nauczyć programować a tego rodzaju tutoriale ich wabią. Efekty są opłakane i mnóstwo tych osób nie jest w stanie podołać nawet najłatwiejszym zadaniom na SPOJu, że o programowaniu użytkowym nie wspomnę.

Tarpauwatratar o taką radę mi chodziło i bardzo za nią dziękuję. Zadanie pokazało że trzeba użyć w nim jakiejś wiedzy której nie mam choć zobaczyłem to dopiero pisząc program.
Nakierowałeś mnie na dobre źródła i mam teraz co czytać ( temat mnie bardzo zainteresował odłożę nawet programowanie Obiektowe na trochę później w związku z tym ). Kurs Pana Zelenta nie wydawał mi się zły, choć nie miałem porównania go do innych. Owszem dało się wyczuć w miarę robienia wcześniejszych zadań ze SPOJ że o wielu rzeczach nie było w nim ( np. bardzo mało informacji o typach zmiennych, nie wspomniał o choćby o BOOL ) ale to wszystko sobie doszukiwałem w miarę potrzeb z innych źródeł.
Odcinki podstawowego kursu obejrzałem wszystkie i teraz widząc co napisałeś o rodzajach algorytmów i o rozwiązywaniu problemów z nimi związanymi czuję jeszcze większy niedosyt.
Zadanie Wiosna Radosna na razie odkładam aż się doszkolę, ale mój nie w pełni działający kod mogę wstawić na Ideone.com jeśli chcecie go zobaczyć z ciekawości.

Dlatego właśnie do Zelenta trzeba podchodzić ostrożnie :wink:

Kod zachowaj dla siebie. Może przyda Ci się w zadaniach, w których trzeba wykonywać wielokrotne sortowania według różnych parametrów.

pomysł, aby posortować rzeczy wg. opłacalności nie jest zły - zajrzałem do swojego rozwiązania (dawno to było), i widzę, że też od tego zacząłem :slight_smile:

niestety dalszej części już nie rozumiem :slight_smile: (ale niewykluczone, że to sortowanie nie ma żadnego znaczenia)

zadanie nie jest bardzo trudne (porównując do innych z tej kategorii), a sam algorytm łatwy do znalezienia i co ważniejsze łatwy do zrozumienia

najciekawsze jest jednak porównanie czasu wykonania - ten sam program ma czas 100 razy krótszy niż 8 lat temu

3 months later

Mam podobne spostrzeżenia (odnośnie Zelenta czy niektórych książek) czy raczej przeczucia biorąc pod uwagę moją wiedzę i umiejętności. Właśnie te odczucia pojawiły mi się przy rozwiązywaniu podobno prostych zadań an SPOJ-u. Właśnie szukałbym czegoś takiego co pozwoliłoby mi poczuć się swobodnie w wydawałoby się prostych problemach. Dopiero później chciałbym napisać coś grubszego. Właśnie to wydaje mi się głównym powodem dlaczego niektóre (może raczej wiekszość) tutoriali i podręczników źle edukuje. Bo chcą zaspokoić potrzebę nieprzygotowanego czytelnika aby ten mógł od razu coś fajnego napisać. Wymagania rynku zmuszają do takiego zachowania.

Trochę masz racji. Pierwszy program w wielu książkach [do nauki języka] to:
printf/cout "Witaj świecie!".
Po przejrzeniu kilku/nastu podręczników, [początków] adept sztuki programowania już umie się przywitać ze światem, ale co dalej...
Na "starym" forum były sobie tutoriale jak to robić na spoj'u; ale przy przenosinach admini dali ciała [czytaj od tyłu ypud]. Czemu nikt nie napisze takich prostych tutoriali teraz, tu na nowym forum? Po prostu starym się nie chce, a młodzi jeszcze nie dorośli? Np ja, stary, skąd mogę mieć pewność, że admini nie wymyślą jutro [pojutrze] nowych przenosin na jeszcze lepszą platformę dyskusji i znowu moja cała praca pójdzie na marne - nie dziękuję postoję.