Knapsack problem(dinamičko programiranje)

poruka: 18
|
čitano: 12.879
|
moderatori: Lazarus Long, XXX-Man, vincimus
1
+/- sve poruke
ravni prikaz
starije poruke gore
13 godina
offline
Knapsack problem(dinamičko programiranje)

Znam da dobar dio vas zna za ovaj problem,pa bih zamolio da mi netko napiše kod za njega,našao sam neko šugavo objašnjenje na engleskom,koje ne razumijem....

Zadatak ide tako da lopov ima ruksak kapaciteta K i kako mu je policija za petama,pokušava ga popuniti tako da vrijednost u ruksaku bude najveća.Svaki predmet odlikuje veličina( kn ) i vrijednost (vn),program treba ispisati najveću moguću vrijednost koju lopov u tom trenutku može ponijeti...Ulazni podaci su N(broj predmeta) , K (kapacitet ruksaka) i zatim u N redova vn(vrijednost) i kn(veličina) svakog predmeta.

 

Hvala unaprijed,ako je moguće neka u kodu nabaci koji komentar :)

griješiti je ljudski al je osjećaj božanski
 
0 0 hvala 0
14 godina
neaktivan
offline
Re: Knapsack problem(dinamičko programiranje)

Uzmes za svaki predmet njegovu vrijednost i podjelis ju sa velicinom da dobijes odnos vrijednost/velicina, i nakon toga uzimas samo one predmete koji imaju najveci omjer.

 

Dakle sortiras te predmete po omjeru vrijednosti, pocnes od onoga koji ima najveci omjer, provjeris stane li u ruksak, ako ne stane ides na iduci po vrijednosti, ako on stane u ruksak, oduzmes njegovu velicinu od velicine ruksaka da dobijes slobodno preostalo mjesto u ruksaku. Pa opet iznova trazis predmet sa najvecim omjerom koji stane u preostalo mjesto ruksaka, to ponavljas dokle god ima mjesta i predmeta koji bi mogli stati.

So then I typed GOTO 500 - and here I am!
Poruka je uređivana zadnji put sri 22.6.2011 20:51 (rustweaver).
13 godina
offline
Re: Knapsack problem(dinamičko programiranje)
rustweaver kaže...

Uzmes za svaki predmet njegovu vrijednost i podjelis ju sa velicinom da dobijes odnos vrijednost/velicina, i nakon toga uzimas samo one predmete koji imaju najveci omjer.

 

Dakle sortiras te predmete po omjeru vrijednosti, pocnes od onoga koji ima najveci omjer, provjeris stane li u ruksak, ako ne stane ides na iduci po vrijednosti, ako on stane u ruksak, oduzmes njegovu velicinu od velicine ruksaka da dobijes slobodno preostalo mjesto u ruksaku. Pa opet iznova trazis predmet sa najvecim omjerom koji stane u preostalo mjesto ruksaka, to ponavljas dokle god ima mjesta i predmeta koji bi mogli stati.

To sam i ja prvotno radio,ali to je greedy algoritam i ne prolazi :/

griješiti je ljudski al je osjećaj božanski
14 godina
offline
Re: Knapsack problem(dinamičko programiranje)
rustweaver kaže...

Uzmes za svaki predmet njegovu vrijednost i podjelis ju sa velicinom da dobijes odnos vrijednost/velicina, i nakon toga uzimas samo one predmete koji imaju najveci omjer.

 

Dakle sortiras te predmete po omjeru vrijednosti, pocnes od onoga koji ima najveci omjer, provjeris stane li u ruksak, ako ne stane ides na iduci po vrijednosti, ako on stane u ruksak, oduzmes njegovu velicinu od velicine ruksaka da dobijes slobodno preostalo mjesto u ruksaku. Pa opet iznova trazis predmet sa najvecim omjerom koji stane u preostalo mjesto ruksaka, to ponavljas dokle god ima mjesta i predmeta koji bi mogli stati.

Koliko se sjećam kad sam čitao o knapsack problemu, bio je tamo dokaz takav način ne daje dobre rezultate.

 

@autor teme: na internetu imaš sto objašnjena na engleskome o knapsack problemu. Malo se potrudi. Ja bih ti da imam vremena. 

Open Source!
13 godina
offline
Re: Knapsack problem(dinamičko programiranje)
captain_soap_McTawish kaže...
rustweaver kaže...

Uzmes za svaki predmet njegovu vrijednost i podjelis ju sa velicinom da dobijes odnos vrijednost/velicina, i nakon toga uzimas samo one predmete koji imaju najveci omjer.

 

Dakle sortiras te predmete po omjeru vrijednosti, pocnes od onoga koji ima najveci omjer, provjeris stane li u ruksak, ako ne stane ides na iduci po vrijednosti, ako on stane u ruksak, oduzmes njegovu velicinu od velicine ruksaka da dobijes slobodno preostalo mjesto u ruksaku. Pa opet iznova trazis predmet sa najvecim omjerom koji stane u preostalo mjesto ruksaka, to ponavljas dokle god ima mjesta i predmeta koji bi mogli stati.

Koliko se sjećam kad sam čitao o knapsack problemu, bio je tamo dokaz takav način ne daje dobre rezultate.

 

@autor teme: na internetu imaš sto objašnjena na engleskome o knapsack problemu. Malo se potrudi. Ja bih ti da imam vremena. 

Pa onda mi daj neki link normalni ,jer ga ja u nisam u stanju nać :/

griješiti je ljudski al je osjećaj božanski
15 godina
odjavljen
offline
Re: Knapsack problem(dinamičko programiranje)
rustweaver kaže...

Dakle sortiras te predmete po omjeru vrijednosti, pocnes od onoga koji ima najveci omjer, provjeris stane li u ruksak, ako ne stane ides na iduci po vrijednosti, ako on stane u ruksak, oduzmes njegovu velicinu od velicine ruksaka da dobijes slobodno preostalo mjesto u ruksaku. Pa opet iznova trazis predmet sa najvecim omjerom koji stane u preostalo mjesto ruksaka, to ponavljas dokle god ima mjesta i predmeta koji bi mogli stati.

Recimo da ti predmet s najvećim omjerom (npr 1.01) zauzima 90 % kapaciteta, a sljedeći predmeti na listi imaju omjer vrijednosti npr 1 i zauzimaju 20 % kapaciteta i nakon 5 takvih imaš predmet koji zauzima 10 % kapaciteta i ima omjer 0,5.

 

Po tvom algoritmu bi imao prvi predmet i zadnji predmet i vrijednost 0,959, dok bi odabirom ovih 5 predmeta manje vrijednosti imao ukupnu vrijednost 1.

Big wheel keep on turning, Proud Mary keep on burning, Trolling, trolling, trolling on the river.
14 godina
neaktivan
offline
Re: Knapsack problem(dinamičko programiranje)

Zato se to zove aproksimacija :D

A sta ja znam... bojim se da nisam dovoljno pametan za rjesavanje tog problema na pravilan nacin.

So then I typed GOTO 500 - and here I am!
13 godina
offline
Re: Knapsack problem(dinamičko programiranje)
rustweaver kaže...

Zato se to zove aproksimacija :D

A sta ja znam... bojim se da nisam dovoljno pametan za rjesavanje tog problema na pravilan nacin.

  Znam kako ti je...{#}

griješiti je ljudski al je osjećaj božanski
14 godina
offline
Re: Knapsack problem(dinamičko programiranje)
rustweaver kaže...

Zato se to zove aproksimacija :D

A sta ja znam... bojim se da nisam dovoljno pametan za rjesavanje tog problema na pravilan nacin.

Ne razumijem kako možeš biti ne pametan za rješavanje problema. Jedino možeš ne imati dovoljno znanja za rješavanje problema.

Evo jedan link:

http://www.cs.berkeley.edu/~vazirani/algorithms/chap6.pdf

 

No ipak mislim da biste prvo rebali početi učiti algoritme ispočetka jer ovako bez ikakvoh znanja o algoritmima, bit će vam vrlo teško razumjeti o čemu se govori. Ja još nisam došao do dinamičkog programiranja pa vam još ne mogu pomoći.

 

EDIT: Ako vas zanima više o algoritmima pogledajte ovu temu:

http://www.bug.hr/forum/topic/programiranje/reference-ucenje-algoritama/97491.aspx

Open Source!
Poruka je uređivana zadnji put čet 23.6.2011 7:39 (captain_soap_McTawish).
13 godina
offline
Knapsack problem(dinamičko programiranje)
Ispocetka?pa nije to matematika...ucis one koje ti trebaju
griješiti je ljudski al je osjećaj božanski
 
0 0 hvala 0
14 godina
offline
Re: Knapsack problem(dinamičko programiranje)
KKristijan kaže...
Ispocetka?pa nije to matematika...ucis one koje ti trebaju

Tvoj je izbor.

 

No mislim da je glupo ići na neke malo složenije algoritme ako nisi savladao jednostavnije i ako ne znaš ništa algoritmima. Algoritmi se uče isto kao matematika. 

Open Source!
14 godina
neaktivan
offline
Re: Knapsack problem(dinamičko programiranje)
captain_soap_McTawish kaže...

Ne razumijem kako možeš biti ne pametan za rješavanje problema. Jedino možeš ne imati dovoljno znanja za rješavanje problema.

Tako sto mi kreativna (desna) strana mozga nadjacava onu logicku (lijevu). Programiranjem sam se prije 11 godina poceo samo iz jednog razloga, htio sam stvarati. Citanje o algoritmima (pogotovo algoritmima ovakve vrste) i nekakvo teoriziranje meni nije zanimljivo (opet utjecaj desne strane). S druge strane, kada neki problem treba vizualizirati u glavi, tu sam kao riba u vodi. Tako uglavnom i rijesavam programske probleme, ono sto ne mogu vizualizirati, ne mogu rijesiti.

 

http://www.angelfire.com/wi/2brains/

http://www.web-us.com/brain/braindominance.htm

http://www.wherecreativitygoestoschool.com/vancouver/left_right/rb_test.htm

 

A sigurno si negdje vidio i onaj test sa balerinom koja se okrece, koji pokazuje koja ti je strana mozga aktivnija u tom trenutku...

 

Puno se moze reci na tu temu, ali cu te ostaviti da sam istrazujes a i debeli je offtopic. Samo cu na kraju zakljuciti da sam ja ono sto se dobije kada se osoba sa dominantnom desnom stranom mozga pokusa baviti programiranjem :D

So then I typed GOTO 500 - and here I am!
13 godina
offline
Re: Knapsack problem(dinamičko programiranje)
captain_soap_McTawish kaže...
KKristijan kaže...
Ispocetka?pa nije to matematika...ucis one koje ti trebaju

Tvoj je izbor.

 

No mislim da je glupo ići na neke malo složenije algoritme ako nisi savladao jednostavnije i ako ne znaš ništa algoritmima. Algoritmi se uče isto kao matematika.

  Učio bih ja sve i po redu da imam otkuda :-D

griješiti je ljudski al je osjećaj božanski
14 godina
offline
Re: Knapsack problem(dinamičko programiranje)
rustweaver kaže...

Kod mene je slična situacija. Meni je lakše kad nešto mogu nekako vizualizirati. Zato volim OOP.

KKristijan kaže...

  Učio bih ja sve i po redu da imam otkuda :-D

Evo jedan uvod:

http://www.cs.berkeley.edu/~vazirani/algorithms/all.pdf

Open Source!
15 godina
offline
Knapsack problem(dinamičko programiranje)

- za ovakav tip problema, dobar primjer bi bila igra Elite... problem količine novca, ponuđene robe, cargo spacea i razlike u cijeni koja se može ostvariti.. u Elit se najbolje ta kombinacija očituje kao 'optimalna' trgovina-zarada... tj kad više manjeih-jeftinijih predmeta mogu dati ukupno veću zaradu od neke druge skuplje robe koja po komadu inače ima veću zaradu... ograničenje je kargo ili ruksak uz dodatak da u ovom primjeru lopov nema-netreba novac za kupnju, koji je u Eliti također bitan dio formule, kao i rizik transporta i sam trošak transporta... dakle ovaj 'lopov' primjer ima par variabli manje od 'igrice'.

 

-eto jednog primjera koristnosti igara (naravno ne trasherskih..).

C64/TurboModul-OpenSourceProject.org.cn.部分作品为网上收集整理,供开源爱好者学习使用
 
0 0 hvala 0
13 godina
neaktivan
offline
Knapsack problem(dinamičko programiranje)

Milslim da vam ja mogu pomoci. Nisam suguran dokle ste stigli i sto ima u onim materijalima jer nisam citao vase prijasnje postove, pa je moguce da moj post bude viska.

Vidio sam da je netko predlagao "greedy"  odnosno pohlepno rjesenje, tako da uzme najvrijednije odnosno stvari s najboljim odnosom.

Takva rjesenja prolaze u slucajevima kada imamo krhke elemente tj. mozemo uzeti neki dio elementa, a padaju u određenim slucajevima kada imamo krute elemente tj moramo ga uzeti cijelog ili nikako. Recimo nekakva zlatna prasina i zlatne poluge bio bi dobar odnos.

 

Kao kod svakog dinamickog programiranja tako i tu cilj je da se zapamti svako poznato stanje, te da se stoga smo jednom racuna.

Iako se u implementaciji da sacuvati puno prostora ja cu ovdje objasniti na "najneoptimalniji" nacin.

 

Daklo stanje DP-a cemo prikazati kao uređeni par dp(x, y) -> najbolje rjesenje (najveca tezina) koja ce stati u ruksak velicine y, koristeci prvih x elemenata.

Dakle kada gradimo dp tablicu to ce izgledati nesto tipa ovo :

 

Za svaki element znamo njegovu velicinu(V[i]) te vrijednost(C[i]).

 

V C

2 2

3 3

4 5

U ovome slucaju se mozda poklope greedy i dp rjesenje ali nije mi se dalo smisljati jedno gdje greedy pada, no siguran sam da uz malo mozganja to mozete smisliti.

Uzimam da svakog elementa imamo beskonacno mnogo, a kasnije cemo obraditi i 0-1 verziju gdje svakog imam jedan.

 

Dakle : Neka nam redovi tablice govore koliko elemenata koristimo, a stupci koliko velik ruksak koristimo :

   1 2 3 4 5 6

1 0 2 2 4 4 6  

2 0 2 3 4 5 5

3 0 2 3 5 5 7

 

Dakle vidimo da je rjesenje koristeci gornja tri elementa 7, tj mozemo ostvariti vrijednost 3.

Sto se da iscitati iz prvog retka, koristeci samo 1. element u ruksak velicine 1 mozemo ostvariti vrijednost 0, jer element nije moguce staviti.

U ruksak velicine 2. moguce je staviti jedan element velicine 2 i ostvariti vrijednost 2, u ruksak velicine 4 moguce je staviti 2 elementa velicine 2 te ostvariti vrijednost 4 ....

Dakle prvi redak popunjavamo pomocu sljedece relacije. dp[1][i] = dp[1][i-V[i]] + C[i];  to znaci koliko sam stavio 1. elemenata u ruksak velicine i-V[i] + 1element sto sada stavljam.

dakle u ruksak velicine 3 stavimo jedan element i ostane nam 1 jedinica prostora prazna. // i-oznacava velicinu ruksaka.

 

U drugom retku imamo sljedecu logiku. U ruksak velicine 1 nije moguce staviti nista(niti prvi niti drugi element), u ruksak velicine 2 moguce je staviti samo prvi element, pa ga i uzimamo.

Eh sada u ruksak velicine 3 gledamo jeli bolje staviti 1 1. element ili 1 2. element ispada da je bolje staviti 1 2. element. ruk velicine 4, jeli bolje staviti 2 1.elementa ili 1 2. element ispada da je bolje staviti 2 1. itd.

Dakle sada popunjavamo relacijom dp[2][i] = max( dp[1][i], dp[2][i-V[i]] + C[i] );

 

... istom logikom dalje.

 

1-0 verzija. Svakog elementa ima samo jedan.

 

   1 2 3 4 5 6

1 0 2 2 2 2 2

2 0 2 3 3 5 5

3 0 2 3 5 5 7

 

Logka je u principu ista samo sto se uvijek gleda na prosli red. Ako nekih elemenata imate vise, gledajte ih razdvojeno.

Kada zelite ocitati dp tablicu onda jos morate imati array gdje spremate koji ste element stavili. Znaci if dp[j-V[i]]  + C[i] > dp[j] best[j] = i;

 

Evo kod :

 

#include <cstdio>
#include <algorithm>
#include <cstring>

using std::max;

const int MAXN = 100; // maksimalan broj stvari
const int MAXV = 100; // maksimalan volumen

int V[ MAXN ]; // velicina elementa
int C[ MAXN ]; // cijena elementa

int dp1[ MAXN ][ MAXN ]; // 1-0 verzija
// [stavi koristeno][velicina ruksaka]
int dp2[ MAXN ];

int N, W; // broj elemenata i volumen

int main()
{
  scanf( "%d%d", &N, &W );
  for ( int i = 0; i < N; ++i )
    scanf( "%d%d", V+i, C+i ) ;

  memset( dp1, 0, sizeof dp1 );
  memset( dp2, 0, sizeof dp2 );

  // 1-0
  for ( int i = 0; i < N; ++i ) // iteriram po elementima
    for ( int j = 0; j <= W; ++j ) { // iteriram po velicini ruksaka
      if ( i == 0 && V[i] <= j ) dp1[i][j] = C[i]; // ako stane u ruksak
      else if ( V[i] <= j )
    dp1[i][j] = max( dp1[i-1][j], dp1[i-1][j-V[i]] + C[i] );
      else
    dp1[i][j] = dp1[i-1][j];
      // sto je bolje napuniti ruksak samo sa i-1 stvari
      // ili je bolje napuniti j-V[i] stvari s i-1 stavit i
      // staviti i-tu stvar ovdje
    }

  for ( int i = 0; i < N; ++i, putchar('\n') )
    for ( int j = 0; j <= W; ++j )
      printf( "%3d", dp1[i][j] );

  printf( "%d\n", dp1[N-1][W] );

  // verzija gdje svake stvari imamo beskonacno
  for( int i = 0; i < N; ++i )
    for ( int j = 0; j <= W; ++j )
      if ( V[i] <= j )
    dp2[j] = max( dp2[j], dp2[j-V[i]] + C[i] );

  printf( "%d\n", dp2[W] );
}
Nadam se da sam bio od pomoci.

Ako postoje neke nejasnoce javite se.

 

EDIT : I naravno i pogotovo greske !!

Poruka je uređivana zadnji put čet 23.6.2011 15:25 (Budimir).
 
1 0 hvala 3
13 godina
neaktivan
offline
Knapsack problem(dinamičko programiranje)

Primjeri klasicnog knapsacka ... Pa tko umire od dosade neka razbija glavu ...

https://www.spoj.pl/problems/SOLDIER/

https://www.spoj.pl/problems/SCUBADIV/

 

 
1 0 hvala 0
1
Nova poruka
E-mail:
Lozinka:
 
vrh stranice