Dynamisch programmeren: wat is het en alles wat u moet weten?

Dynamisch programmeren
Afbeeldingsbron: AfterAcademy
Inhoudsopgave Verbergen
  1. Wat is dynamisch programmeren?
  2. Hoe werkt dynamisch programmeren?
    1. #1. Top-downbenadering
    2. #2. Bottom-up benadering
  3. Kenmerken van dynamisch programmeren
    1. #1. Deelproblemen overlappen elkaar
    2. #2. Onderbouw heeft optimale eigenschappen
  4. Gebruik van dynamisch programmeren in de echte wereld
    1. #1. Knapzak probleem
    2. #2. Alle paar kortste pad
    3. #3. Naad snijwerk
    4. #4. Machine learning en genomica
    5. #5. cryptografie
  5. Wat is een voorbeeld uit de echte wereld van dynamisch programmeren?
  6. Hoe dynamische programmeerproblemen op te lossen?
    1. #1. Erken het probleem met dynamisch programmeren
    2. #2. Bepaal de oorzaken van het probleem
    3. #3. Kies tussen een iteratieve en een recursieve methode
    4. #4. Neem een ​​geheugensysteem op
    5. #5. Zet de herhalingsrelatie onder woorden
  7. Algoritme dynamische programmering
    1. Verschillende soorten dynamische programmeeralgoritmen
    2. #2. Floyd-Warshall-algoritme
  8. Hoe lost een dynamisch programmeeralgoritme Lcs-problemen sneller op dan een recursieve techniek?
  9. Wat zijn de dynamische programmeerproblemen in Python
    1. #1. Knapzak (0-1) Begrensd
    2. #2. 0/1 Knapzak begrensde memovorming
    3. #3. Probleem met gelijke deelverzamelingen
  10. Voordelen van dynamisch programmeren
    1. #1. Effectief middel
    2. #2. Vergemakkelijkt het gemakkelijk vinden van problemen
    3. #3. Efficiënt
    4. #4. Effectief wanneer een probleem meerdere oplossingen heeft
  11. Wat zijn de nadelen van dynamisch programmeren?
    1. #1. Deelproblemen die steeds terugkeren
    2. #2. Compliciteit in tijd en ruimte
    3. #3. Kader voor de kwestie
    4. #4. Moeilijk in praktijk te brengen
  12. Tot slot
  13. Veelgestelde vragen over dynamisch programmeren
  14. Wat is het verschil tussen lineaire programmering en dynamische programmering?
  15. Hoe moeilijk is het om dynamisch programmeren te leren?
  16. Is dynamisch programmeren erg moeilijk?
  17. Vergelijkbare artikelen
  18. Referentie

Dynamisch programmeren is een term die waarschijnlijk al lang in het rond is gegooid als je al een tijdje in het veld zit. Het onderwerp komt regelmatig ter sprake tijdens design review meetings en in de dagelijkse interacties van ingenieurs, en het is ook een centraal punt in technische interviews. De verdeel-en-heers-strategie is een onfeilbare methode om elk doel te bereiken. Bij computerprogrammering is ditzelfde idee waar. Talrijke moeilijkheden hebben subtypen die kunnen worden geïsoleerd en afzonderlijk kunnen worden behandeld, waardoor de uiteindelijke oplossing van het primaire probleem mogelijk wordt. In dit artikel bespreken we het dynamische programmeeralgoritme en Python.

Wat is dynamisch programmeren?

Dynamisch programmeren is een methode om complexe problemen op te lossen door ze eerst terug te brengen tot eenvoudigere problemen en vervolgens de oplossingen voor die eenvoudigere problemen te gebruiken als bouwstenen om het oorspronkelijke probleem op te lossen. 

We verdelen het probleem in behapbare brokken. In de meeste gevallen is het enige echte verschil tussen het probleem van de ouder en dat van het kind hun relatieve omvang. Deze miniproblemen kunnen dus worden opgesplitst in nog meer miniproblemen, enzovoort, voor onbepaalde tijd. Stel je voor dat een vraagstuk en zijn verschillende deelproblemen een boom vormen. Eerst worden de "blad"-problemen aangepakt, gevolgd door hun "ouder"-problemen, en zo verder in de probleemboom. Terwijl we kleinere moeilijkheden aanpakken, registreren we onze voortgang voor later gebruik. Hierdoor kunnen we dat deel van het probleem in de toekomst overslaan. 

Deze methode is vergelijkbaar met de verdeel-en-heerstechniek omdat het een probleem opsplitst in kleinere problemen die onafhankelijk kunnen worden opgelost en vervolgens worden gecombineerd om de uiteindelijke oplossing te verkrijgen.

Hoe werkt dynamisch programmeren?

Dynamisch programmeren is effectief omdat het moeilijke kwesties vereenvoudigt door ze op te splitsen in samenstellende delen. De volgende stap is het vinden van de beste antwoorden op deze uitdagingen. De resultaten van deze procedures kunnen in het geheugen worden opgeslagen, zodat de overeenkomstige oplossingen uit de opslag kunnen worden gehaald en zonder verdere berekeningen kunnen worden gebruikt. Ook kan de oplossing worden opgeslagen om te voorkomen dat eerder opgeloste subproblemen opnieuw worden berekend. 

Er zijn twee methoden om dynamische programmering uit te voeren:

#1. Top-downbenadering

In de informatica worden problemen meestal opgelost door oplossingen recursief te construeren, of door de resultaten van eerdere stappen te gebruiken om het probleem aan te pakken. Het is mogelijk om de oplossingen van de subproblemen te onthouden of in een tabel bij te houden als ze vergelijkbaar zijn. De top-down methode is gebaseerd op leren uit het hoofd. Memoriseren is hetzelfde als het tweemaal uitvoeren van recursie en caching. Recursie omvat het indirect aanroepen van de functie, terwijl caching het bijhouden van tussentijdse resultaten inhoudt.

Enkele van de vele voordelen van de top-downbenadering zijn:

  • De top-down methode is eenvoudig te begrijpen en toe te passen. Om beter te begrijpen wat er moet gebeuren, deconstrueert deze methode problemen in hun samenstellende elementen. Elke nieuwe ontwikkeling brengt de verlichting van een voorheen onoverkomelijke hindernis met zich mee. Sommige stukken kunnen zelfs van toepassing zijn op andere problemen.
  • Het maakt de oplossing van deelproblemen op aanvraag mogelijk. De top-down methode maakt het mogelijk om problemen op te splitsen in beheersbare brokken, waarbij de oplossingen voor die brokken worden opgeslagen voor later gebruik. Vervolgens kunnen klanten om hulp vragen bij het repareren van elk onderdeel. 
  • Foutopsporing is ook vereenvoudigd. Door een probleem in kleinere stukjes te verdelen, wordt het gemakkelijker om het antwoord te volgen en mogelijke fouten te zien. 

Hier volgen enkele van de nadelen van het gebruik van een top-downbenadering:

  • De top-downstrategie maakt gebruik van de recursiemethode, die meer geheugen in beslag neemt in de call-stack dan andere benaderingen. Dit resulteert uiteindelijk in een afname van de prestaties. Bovendien kan een stackoverloop optreden als de recursie te ver teruggaat in het verleden.

#2. Bottom-up benadering

Nadat de oplossing van een probleem is uitgedrukt in termen van de deelproblemen op een manier die op zichzelf terugkeert, kunnen gebruikers het probleem herschrijven met behulp van de bottom-upbenadering, waarbij ze eerst de kleinere deelproblemen oplossen en vervolgens hun oplossingen toepassen op de grotere. . 

In tegenstelling tot de top-down methode wordt bij de bottom-up methode de recursie geëlimineerd. Daarom voegen de recursieve functies geen onnodige overhead toe en veroorzaken ze geen overloop van de stapel. Bovendien maakt het datacompressie mogelijk. De temporele complexiteit van recursie wordt verminderd doordat het niet meer nodig is om dezelfde waarden opnieuw te berekenen. 

Enkele voordelen van vanaf de basis werken zijn als volgt:

  • Het bepaalt eerst hoe een enorm probleem zal worden opgebouwd uit kleinere, herbruikbare deelproblemen.
  • Door recursie af te schaffen, helpt het om het beschikbare geheugen beter te gebruiken. De timingcomplexiteit wordt verminderd als bijwerking. 

Kenmerken van dynamisch programmeren

Er zijn twee onderscheidende kenmerken van dynamisch programmeren:

#1. Deelproblemen overlappen elkaar

Aanpassingen van een primair probleem die beter beheersbaar zijn, worden 'subproblemen' genoemd. De rij van Fibonacci, waarin elk getal gelijk is aan de som van de twee voorgaande (0, 1, 1, 2, 3, 5, 8,...). U kunt de taak van het vinden van de n-de waarde in de Fibonacci-reeks opdelen in meer beheersbare brokken. Naarmate je oplossingen vindt door hetzelfde subprobleem keer op keer aan te pakken, worden deze overlappende reeksen moeilijkheden steeds moeilijker op te lossen.

Dynamisch programmeren kan worden gebruikt om grote programmeertaken op te splitsen in beheersbare brokken vanwege het universele voorkomen van overlappende subproblemen.

#2. Onderbouw heeft optimale eigenschappen

De eigenschap van optimale onderbouw manifesteert zich wanneer het mogelijk is om uit de oplossingen voor alle deelproblemen een optimale oplossing te creëren. Om recursie te laten werken, moet u het antwoord dat u uit elke overlapping haalt, toepassen op het hele probleem. De optimale onderbouweigenschap wordt weergegeven door het hele probleem wanneer, zoals in het geval van de Fibonacci-reeks, elk deelprobleem een ​​oplossing heeft die kan worden toegepast op het volgende deelprobleem in de reeks om de waarde ervan te bepalen.

Gebruik van dynamisch programmeren in de echte wereld

Hier zijn de toepassingen van dynamisch programmeren.

#1. Knapzak probleem

Dynamische programmering is op grote schaal gebruikt om het knapzakprobleem op te lossen. Dit zijn de problemen waarmee we worden geconfronteerd:

De ideale waarde voor elk subnummer, bepaald door het aantal items in kwestie en de hoeveelheid resterende ruimte in de knapzak, kan worden opgeslagen in een tweedimensionale array, waardoor dit probleem snel kan worden opgelost. We kunnen de waarde maximaliseren door het huidige item in elke fase op te nemen of uit te sluiten. Het antwoord is te vinden in de rechterbenedenhoek van de array.

Het knapzakprobleem kan in een groot aantal verschillende contexten worden gebruikt, van het inpakken van bagage tot het nemen van investeringsbeslissingen tot het toewijzen van middelen.

#2. Alle paar kortste pad

Het probleem met het kortste pad in een gewogen grafiek is een ander typisch gebruik van dynamisch programmeren. Met behulp van technieken zoals Floyd-Warshall of Bellman-Ford kunnen we het kortste pad vinden tussen twee gegeven paren knooppunten.

Om het kortste pad tussen twee gegeven knooppunten bij te houden, maken deze algoritmen gebruik van een driedimensionale array. Om bij te houden hoe ver ze van het startpunt verwijderd zijn, vergelijken ze het resultaat ook met de afstand tussen het startpunt en het tussenliggende knooppunt in elke fase. De iteraties zijn immers voltooid, de uiteindelijke oplossing is de afstandsmatrix.

Er zijn verschillende toepassingen voor het oplossen van het probleem van het kortste pad met alle paren, zoals bij netwerkanalyse, routering, navigatie, analyse van sociale netwerken, enz.

#3. Naad snijwerk

Op het gebied van beeldverwerking is naadsnijden een intrigerende toepassing van dynamisch programmeren. De taak die voorhanden is, is om de grootte van een afbeelding te verkleinen zonder de essentiële kenmerken ervan te wijzigen. Energiezuinige routes in een afbeelding, ook wel naden genoemd, kunnen worden gebruikt om pixels af te trekken of toe te voegen om dit effect te bereiken.

Met behulp van dynamische programmering kunnen we de cumulatieve energie van elke pixel in de afbeelding berekenen op basis van de gradiënt en buren, en die informatie vervolgens gebruiken om te bepalen welke naden moeten worden verwijderd of toegevoegd. Vervolgens kunnen we, door vanaf de onderkant van de afbeelding omhoog te werken, de naad met de minste hoeveelheid potentiële energie lokaliseren. Deze methode kan opnieuw worden gebruikt totdat de gewenste grootte is bereikt.

Bovendien kunnen afbeeldingen worden vergroot/verkleind, bijgesneden, opnieuw gericht en meer met behulp van naadsnijden.

#4. Machine learning en genomica

Machine learning en genomica-uitdagingen zoals sequentie-uitlijning, verborgen Markov-modellen en fylogenetische bomen zijn allemaal geschikt voor het probleemoplossend vermogen van dynamisch programmeren.

Het uitlijnen van meerdere reeksen symbolen (vaak DNA of eiwitten) om overeenkomsten te ontdekken, wordt sequentie-uitlijning genoemd. Dit kan licht werpen op hun evolutionaire verbanden, functies in de samenleving of structurele kenmerken. Optimale uitlijningen kunnen worden gevonden via dynamisch programmeren door scores toe te kennen aan overeenkomsten en mismatches tussen sequenties.

Probabilistische modellen, bekend als Hidden Markov-modellen, worden gebruikt om tijdreeksgegevens te beschrijven die afhankelijk zijn van onbekende toestanden. Ze zijn nuttig voor het modelleren van moeilijke fenomenen zoals spraakherkenning, NLP, bio-informatica, enz. Wanneer een reeks observaties wordt gegeven, kunnen dynamische programmeertechnieken zoals Viterbi en Forward-Backward de meest waarschijnlijke volgorde van verborgen toestanden bepalen.

Fylogenetische bomen tonen de verbindingen tussen soorten of genen in de loop van de tijd. Het is mogelijk om gemeenschappelijke voorouders, datums van divergentie en evolutionaire gebeurtenissen af ​​te leiden uit deze overeenkomsten. Ook kan een dynamisch programmeeralgoritme zoals Fitch en Sankoff worden gebruikt om optimale fylogenetische bomen te genereren met behulp van sequentiegegevens.

#5. cryptografie

Cryptografie, de studie van geheime communicatie, profiteert ook van het probleemoplossend vermogen van dynamisch programmeren. Versleuteling, ontsleuteling, digitale handtekeningen, authenticatie en andere soortgelijke processen maken allemaal deel uit van cryptografie.

Versleuteling zet informatie om van voor mensen leesbaar naar leesbaar met een geheime sleutel. Decodering is het proces waarbij versleutelde gegevens weer worden omgezet in leesbare tekst met behulp van de originele sleutel of een nieuwe. Met digitale handtekeningen kan de authenticiteit en integriteit van een bericht of document worden geverifieerd. Door de inloggegevens van de afzender of de ontvanger te controleren, kan de identiteit van de afzender of ontvanger worden geverifieerd.

Verschillende soorten cryptografie, waaronder dynamische sleutelcryptografie, op code gebaseerde cryptografie en op dynamische programmering gebaseerde cryptografie, kunnen allemaal worden geïmplementeerd met dynamische programmering.

Dynamische sleutelcryptografie is een mechanisme voor het versleutelen en ontsleutelen van berichten met constant veranderende sleutels. Sleutels die "dynamisch" zijn, zijn sleutels die in de loop van de tijd evolueren of als reactie op andere factoren. Dit maakt ze veiliger dan statische sleutels, die kwetsbaar zijn voor aanvallen. Het is mogelijk om dynamische programmering te gebruiken om sleutels te genereren en up-to-date te houden bij het implementeren van dynamische sleutelcryptografie.

Met behulp van een techniek die bekend staat als op code gebaseerde cryptografie, is het mogelijk om berichten te versleutelen en te ontsleutelen door daarbij foutcorrigerende codes te gebruiken. Het is mogelijk om transmissiefouten op te lossen met foutcorrigerende codes. Het gebruik van op code gebaseerde cryptografie wordt algemeen beschouwd als kwantumbestendig, omdat het beveiligd is tegen aanvallen van kwantumcomputers. Dynamische programmering kan worden gebruikt om communicatie te coderen en te ontcijferen met behulp van een codegebaseerd cryptosysteem.

Als een methode voor het versleutelen en ontsleutelen van gegevens, vertrouwt op dynamische programmering gebaseerde cryptografie op een dynamisch programmeeralgoritme. Om optimalisatie-uitdagingen aan te pakken, verdelen dynamische programmeertechnieken het probleem doorgaans in een reeks eenvoudigere deelproblemen. Dynamische programmeercryptografie maakt gebruik van knapzak, kortste pad en snijwerk.

Wat is een voorbeeld uit de echte wereld van dynamisch programmeren?

Talloze voorbeelden van real-world softwaretoepassingen gebruiken dynamische programmering om flexibiliteit en efficiëntie te behouden en tegelijkertijd hun resource-voetafdruk op het hostsysteem te verkleinen. Sommige gevallen zijn als volgt:

  • Google Maps. Google Maps maakt gebruik van dynamische programmering om de snelste route van een bepaald vertrekpunt naar verschillende bestemmingen te vinden.
  • Netwerken. Sequentiële gegevensoverdracht van een enkele afzender naar meerdere ontvangers.
  • Spellingcontrole. Het algoritme voor de bewerkingsafstand bepaalt het aantal stappen dat nodig is om het ene woord in het andere te transformeren en geeft een kwantitatieve maat voor de mate van ongelijkheid tussen de twee woorden. 
  • Software voor plagiaat. Methoden voor documentafstand helpen bij het bepalen van de gelijkenis van tekstdocumenten.
  • Zoekmachines. Om te bepalen hoe vergelijkbaar twee stukjes internetinhoud eigenlijk zijn.

Hoe dynamische programmeerproblemen op te lossen?

Het leren van de formule voor het oplossen van dynamische programmeerproblemen is de volgende stap na het begrijpen van het concept van dynamisch programmeren. Hier zijn een paar suggesties voor het toepassen van dynamisch programmeren op het probleem in kwestie en om tot een werkbare oplossing te komen:

#1. Erken het probleem met dynamisch programmeren

Het belangrijkste onderdeel is het besef dat een dynamisch programmeeralgoritme de gespecificeerde probleemstelling kan oplossen. Om dit probleem op te lossen, moet eerst worden bepaald of elk van de probleemstellingen als een functie in kleinere delen kan worden opgesplitst.

#2. Bepaal de oorzaken van het probleem

Als je al tot de conclusie bent gekomen dat dynamisch programmeren het juiste hulpmiddel voor de taak is, is de volgende stap het identificeren van de recursieve structuur van het probleem tussen de samenstellende subproblemen. In dit geval moet u rekening houden met de veranderlijke aard van de probleemcondities. Deze variabele kan een arraypositie of probleemoplossingssnelheid zijn.

Daarnaast is het tellen van de samenstellende delen van het probleem cruciaal.

#3. Kies tussen een iteratieve en een recursieve methode

Om dynamische programmeerproblemen op te lossen, kunt u iteratieve of recursieve benaderingen gebruiken. Uit wat tot nu toe is gezegd, is het veilig om te zeggen dat de recursieve methode de voorkeur heeft. Alle bovengenoemde overwegingen staan ​​echter op zichzelf, ongeacht de gekozen methode om het probleem op te lossen.

Voor zowel de recursieve als de iteratieve benadering moet u de herhalingsrelatie en het basisscenario van het probleem specificeren.

#4. Neem een ​​geheugensysteem op

Bij het aanpakken van een probleem met een vergelijkbare structuur kan het nuttig zijn om eerdere ervaringen met het omgaan met vergelijkbare subproblemen te herinneren. De tijdcomplexiteit van het probleem zal hierdoor afnemen. De tijdcomplexiteit van een taak kan exponentieel toenemen als we dezelfde deelproblemen keer op keer blijven oplossen zonder memorisatie te gebruiken.

#5. Zet de herhalingsrelatie onder woorden

Bij het oplossen van een probleem slaan veel programmeurs het definiëren van de herhalingsrelatie over en gaan direct over tot coderen. U begrijpt het probleem beter en kunt het sneller coderen als u de herhalingsrelatie expliciet kunt uitdrukken voordat u begint.

Algoritme dynamische programmering

De meeste toepassingen van dynamisch programmeren bevatten het recursieve algoritme. Het gebruik van dynamische programmering voor optimalisatie houdt in dat recursie inherent is aan de meeste optimalisatieproblemen.

Het is echter niet mogelijk om all-recursieve problemen op te lossen met dynamisch programmeren. Een recursie kan alleen de oplossing vinden door een verdeel-en-heersstrategie, tenzij er sprake is van overlappende subproblemen, zoals bij het Fibonacci-reeksprobleem.

Dit komt omdat de onderliggende subproblemen in een recursief algoritme zoals Merge Sort elkaar niet overlappen, waardoor het gebruik van dynamische programmering wordt uitgesloten.

Verschillende soorten dynamische programmeeralgoritmen

Hier zijn de verschillende soorten dynamische programmeeralgoritmen.

#1. Langste gemeenschappelijke subreeks

Het is mogelijk dat de elementen van de langste gemeenschappelijke subreeks (LCS) in elke volgorde in de oorspronkelijke reeksen verschijnen; de LCS wordt gedefinieerd als de langste subreeks die gemeenschappelijk is voor alle gespecificeerde reeksen.

Als er twee reeksen S1 en S2 zijn, wordt een reeks Z die een subreeks is van zowel S1 als S2 hun gemeenschappelijke subreeks genoemd. Als extra vereiste moet Z bestaan ​​uit een strikt stijgende reeks van de indices van verzamelingen S1 en S2.

De indices van de geselecteerde elementen in Z moeten strikt toenemen om een ​​stijgende reeks te vormen.

#2. Floyd-Warshall-algoritme

Het vinden van het kortste pad tussen elk paar hoekpunten in een gewogen grafiek is het doel van het Floyd-Warshall-algoritme. Deze methode verwerkt grafieken met gewichten in beide richtingen. Aan de andere kant mislukt het voor cycli waarin de som van hun randen negatief is.

Floyd's algoritme, Roy-Floyd-algoritme, Roy-Warhshall-algoritme en WFI-algoritme zijn allemaal namen voor het Floyd-Warhshall-algoritme.

Dit algoritme gebruikt een dynamische programmeertechniek om optimale snelkoppelingen te vinden.

Hoe lost een dynamisch programmeeralgoritme Lcs-problemen sneller op dan een recursieve techniek?

Dynamisch programmeren vermindert de overhead van het aanroepen van een functie. Het onthoudt de uitkomst van elke functieaanroep, zodat volgende oproepen gebruik kunnen maken van de opgeslagen gegevens zonder hetzelfde werk te herhalen.

Elke keer dat een element van X wordt vergeleken met een element van Y, worden de resultaten naar een tabel geschreven, zodat ze kunnen worden gebruikt in latere berekeningen in het bovengenoemde dynamische proces.

Daarom is de looptijd van een dynamische methode gelijk aan de tijd die nodig is om de tabel te vullen (O(mn)). De complexiteit van het recursieve algoritme daarentegen is 2max(m, n). Lees ook Hoe u het juiste type versleutelingsalgoritme kiest voor uw zakelijke behoeften

Wat zijn de dynamische programmeerproblemen in Python

Door gebruik te maken van dynamische programmering kan men de meest geschikte oplossing bepalen voor een willekeurig aantal verschillende probleemstellingen. In het volgende zullen we enkele van de meest gevraagde beroemde probleemstellingen bespreken en een korte uitleg geven, samen met de juiste Python-code.

#1. Knapzak (0-1) Begrensd

In deze situatie krijg je de prijzen en gewichten van N goederen en moet je ze in een rugzak met capaciteit W passen; het doel is om het aantal gekozen items te minimaliseren en toch alles in de knapzak te passen.

De meeste technische sollicitatiegesprekken voor goederenorganisaties vereisen dat kandidaten het knapzakprobleem oplossen, wat een klassiek voorbeeld is van een dynamische programmeertechniek.

Probleemstelling Stel dat je een tas hebt met capaciteit W en een lijst met dingen, elk met een gewicht en bijbehorende winst. Het doel is om de inkomsten te maximaliseren door effectief slecht te vullen.

Het antwoord is om een ​​tabel te maken met kolommen voor elk denkbaar gewicht tussen 1 en W en rijen voor de gewichten die je daadwerkelijk selecteert. Deze tabel gaat bekend staan ​​als dp[][]. Als 'j' de capaciteit van de rugzak is en de eerste 'i'-elementen in de reeks gewicht/item zijn inbegrepen, dan geeft de staat /cell dp[i][j] in de tabel de hoogst mogelijke winst aan.

Als gevolg hiervan zal de waarde in de laatste cel de oplossing aangeven. Het is belangrijk om alleen datgene in te pakken dat de gewichtsbeperking van de rugzak niet overschrijdt. Er zijn twee alternatieven voor het criterium “weight>wt[i-1]” waarbij alle kolommen gevuld kunnen worden. 

#2. 0/1 Knapzak begrensde memovorming

Vul een zak met items van bekend gewicht en winst, maat K. Uw doel is om uw inkomsten te maximaliseren. Hier gebruiken we memo's in plaats van tabellen om te zien of we het probleem kunnen oplossen.

Het bovenstaande 0/1 knapzakprobleem maakte gebruik van een bottom-up strategie om een ​​oplossing te vinden, terwijl dit probleem een ​​top-down benadering gebruikt gebaseerd op memorisatie om een ​​oplossing te verkrijgen.

Dynamisch programmeren maakt gebruik van memorisatie om de noodzaak te verminderen om dezelfde delen van het probleem meerdere keren op te lossen. Dit elimineert de noodzaak om het subprobleem voortdurend op te lossen en stroomlijnt het proces van het genereren van output.

Probleemstelling Stel dat je een tas hebt met capaciteit W en een lijst met dingen, elk met een gewicht en bijbehorende winst. Als de zak vol is met zoveel mogelijk efficiëntie, kan men het hoogste potentiële winstniveau behalen.

De oplossing is om eerst een tweedimensionale array te construeren om de definitieve antwoorden op de individuele deelproblemen te bevatten. De kolommen van de tabel geven een lijst van alle mogelijke gewichten tussen 1 en W, verdelen het in zoveel secties, en de rijen tonen de gewichten die u op elk gegeven moment selecteert. 

We gebruiken een dp-array om elk opgelost subprobleem bij te houden. In plaats van een eerder opgelost subprobleem op te lossen, geven we gewoon het antwoord terug.

#3. Probleem met gelijke deelverzamelingen

Zoek een partitie van de gegeven set zodat het totaal van items in beide subsets hetzelfde is met behulp van dynamische programmering om het probleem van de gelijke subset op te lossen. Naast de andere namen is het gelijke subsetprobleem (of partitieprobleem) een uitstekende illustratie van de kracht van dynamisch programmeren.

De huidige taak vereist dat we de array arr in tweeën delen, zodat elk van de volgende subsets dezelfde totale grootte heeft.

Als oplossing moeten we een tweedimensionale array bouwen met afmetingen van (sum/2+1)*(target+1). Hier kunnen de resultaten van het splitsen van de originele array voor elke subset en elke som worden opgeslagen en later worden opgehaald. De eerste dimensie van de array vertegenwoordigt de verschillende subsets die kunnen worden gemaakt, terwijl de tweede dimensie van de array de verschillende sommen vertegenwoordigt die kunnen worden berekend door subsets te combineren.

Voordelen van dynamisch programmeren

Hier zijn enkele voordelen van dynamisch programmeren.

#1. Effectief middel

Dynamisch programmeren is een krachtig hulpmiddel om optimale oplossingen te vinden voor vraagstukken met een optimale onderbouw en overlappende deelproblemen. Door ze op te splitsen in behapbare stukken, zijn deze uitdagingen gemakkelijker aan te pakken met de methode. Dynamisch Programmeren is in staat om een ​​optimale oplossing te creëren door repetitieve berekeningen te vermijden en antwoorden op deelproblemen te hergebruiken.

#2. Vergemakkelijkt het gemakkelijk vinden van problemen

Het oplossen van een moeilijk probleem kan gemakkelijker zijn door het eerst op te splitsen in eenvoudigere delen. Het maakt complexe problemen gemakkelijker aan te pakken door ze op te splitsen in beter beheersbare brokken. Deze methode vereenvoudigt de oplossing en maakt het probleem toegankelijker.

#3. Efficiënt

Door onnodige berekeningen te elimineren en eerder opgeloste subproblemen te hergebruiken, kan dynamisch programmeren de tijd die nodig is om een ​​probleem op te lossen aanzienlijk verkorten. Wanneer de deelproblemen elkaar overlappen, kan de methode helpen door het totale aantal maatregelen dat nodig is om het probleem op te lossen te verminderen.

#4. Effectief wanneer een probleem meerdere oplossingen heeft

Dynamisch programmeren kan helpen bepalen welke van verschillende mogelijke verklaringen het meest waarschijnlijk is. Als er verschillende haalbare opties zijn om een ​​probleem op te lossen, kan deze methode ons helpen de beste te vinden.

Wat zijn de nadelen van dynamisch programmeren?

Hier zijn enkele van de nadelen van dynamisch programmeren.

#1. Deelproblemen die steeds terugkeren

Dynamisch programmeren werkt het beste wanneer het probleem overlappende subproblemen heeft, wat niet altijd het geval hoeft te zijn. Het gaat niet werken en het zal u waarschijnlijk niet de beste oplossing bieden als de individuele problemen elkaar niet kruisen.

#2. Compliciteit in tijd en ruimte

Als het probleem groot is, kan dynamisch programmeren veel geheugen en opslagruimte vergen, waardoor de tijd- en ruimtecomplexiteit van de oplossing toeneemt. Met behulp van geheugen slaat de aanpak tussentijdse resultaten op in een tabel of een memoisatietabel.

#3. Kader voor de kwestie

Hoewel dynamisch programmeren effectief is voor bepaalde probleemstructuren, is het niet altijd de beste keuze. Deze methode werkt het beste wanneer het probleem overlappende subproblemen heeft, en is daarom mogelijk niet van toepassing op andere situaties.

#4. Moeilijk in praktijk te brengen

 Dynamisch programmeren vereist een grondige kennis van algoritmen en datastructuren, waardoor het een uitdaging is om het voor beginners te implementeren. De methode vereist voorafgaand nadenken en grondige vertrouwdheid met het probleem.

Tot slot

Concluderend, dynamisch programmeren is een effectieve methode om antwoorden te vinden, hoewel andere benaderingen de voorkeur verdienen. Het is van cruciaal belang om de voor- en nadelen te kennen en de juiste methode te kiezen op basis van het probleem. Voor problemen met een optimale onderbouw en overlappende deelproblemen kan Dynamisch Programmeren een optimale oplossing opleveren; deze methode is echter niet altijd toepasbaar. 

Hoewel het moeilijk te ontwikkelen is en veel geheugen gebruikt, maakt het vermogen om het probleemoplossende proces te stroomlijnen en de rekentijden te verkorten het tot een belangrijk hulpmiddel voor computerwetenschappers en wiskundigen.

Veelgestelde vragen over dynamisch programmeren

Wat is het verschil tussen lineaire programmering en dynamische programmering?

Voor lineaire optimalisatieproblemen hebben we het algoritme voor lineaire programmering (LP), en voor generieke niet-lineaire optimalisatieproblemen met niet-convexe beperkingen hebben we dynamische programmering (DP), die de globale optimaliteit van een oplossing garandeert.

Hoe moeilijk is het om dynamisch programmeren te leren?

Het is algemeen bekend dat dynamisch programmeren een complex onderwerp is, vooral voor nieuwkomers op het gebied van informatica. Men kan echter gemakkelijk dynamisch programmeren leren met een goed begrip van de basisprincipes en voldoende oefening.

Is dynamisch programmeren erg moeilijk?

Ze zijn moeilijk! Om te beginnen kan het idee van dynamische programmeermethoden moeilijk te bevatten zijn. Elke deskundige programmeur zou bevestigen dat het beheersen van DP een aanzienlijke tijdsbesteding vereist. De vaardigheid om een ​​probleem op te splitsen in zijn samenstellende delen en het weer in elkaar te zetten tot een werkbaar geheel is ook noodzakelijk.

Vergelijkbare artikelen

  1. PROJECT TIME MANAGEMENT: processen, tools en software voor effectief beheer
  2. AMAZON SEO: hoe u uw producten kunt optimaliseren om beter te scoren
  3. MEEST POPULAIRE PROGRAMMEERTALEN: Gids voor 2023
  4. WAT IS COMPUTERPROGRAMMERING: voorbeelden, typen, cursussen en software
  5. Wills Online: beste online testamentmakers.

Referentie

Laat een reactie achter

Uw e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd *

Dit vind je misschien ook leuk