Pagini recente » Monitorul de evaluare | Diferente pentru happy-coding-2007/solutii intre reviziile 40 si 41 | Monitorul de evaluare | Diferente pentru happy-coding-2007/solutii intre reviziile 26 si 27 | Diferente pentru happy-coding-2007/solutii intre reviziile 31 si 32
Nu exista diferente intre titluri.
Diferente intre continut:
Vom calcula costurile $cmin[i]$, reprezentand costul total minim pentru a satisface cererile din lunile $1, 2, .., i$. Algoritmul este descris in continuare in pseudocod:
==code(c) |
* $cmin[ 0 ] = 0$
* $pentru i de la 1 la N$
** $cmin[i]=infinit$
** $pentru j de la 1 la i$
*** $cost_total = cmin[j-1] + F[j] + C[j] * D[j]$
*** $cost_stocare=S[j]$
*** $pentru k de la j+1 la i$
**** $cost_total = cost_total + (C[j]+cost_stocare) * D[k]$
**** $cost_stocare = cost_stocare + S[k]$
*** $daca cost_total < cmin[i] atunci$
**** $cmin[i]=cost_total$
cmin[ 0 ] = 0
pentru i de la 1 la N
cmin[i]=infinit
pentru j de la 1 la i
cost_total = cmin[j-1] + F[j] + C[j] * D[j]
cost_stocare=S[j]
pentru k de la j+1 la i
cost_total = cost_total + (C[j]+cost_stocare) * D[k]
cost_stocare = cost_stocare + S[k]
daca cost_total < cmin[i] atunci
cmin[i]=cost_total
==
Se variaza valoarea lui $i$ de la $1$ la $N$ si pentru fiecare valoare incercam sa calculam $cmin[i]$. Pentru aceasta, incercam toate valorile $j ≤ i$ care pot reprezenta luna in care sunt produse kilogramele de cascaval necesare in luna $i$. Apoi calculam costul total pentru cazul in care luna $j$ produce cantitatea de cascaval necesara pentru a satisface cererile din lunile $j, j+1, .., i$. In cele din urma vom avea in $cmin[i]$ minimul dintre costurile corespunzatoare fiecarei variante de alegere a lunii $j$. Costul total minim pentru toate cele $N$ luni il avem in $cmin[N]$. Bineinteles, aceasta solutie nu se incadreaza in limita de timp.
Algoritmul descris anterior are complexitatea $O(N^3^). El se poate optimiza, insa, usor la complexitatea $O(N^2^)$.
* $cmin[ 0 ] = 0$
* $pentru i de la 1 la N$
** $cmin[i] = infinit$
** $dtotal = 0$
** $cost_stocare = 0$
** $pentru j de la i la 1$
*** $cost_stocare = cost_stocare + S[j] * dtotal$
*** dtotal = dtotal + D[j]
*** cost_productie = F[j] + C[j] * dtotal
*** cost_total = cmin[j-1] + cost_productie + cost_stocare
*** daca cost_total < cmin[i] atunci
**** cmin[i]=cost_total
==code(c) |
cmin[ 0 ] = 0
pentru i de la 1 la N
cmin[i] = infinit
dtotal = 0
cost_stocare = 0
pentru j de la i la 1
cost_stocare = cost_stocare + S[j] dtotal
dtotal = dtotal + D[j]
cost_productie = F[j] + C[j] dtotal
cost_total = cmin[j-1] + cost_productie + cost_stocare
daca cost_total < cmin[i] atunci
cmin[i]=cost_total
==
Optimizarea adusa este minora, dar importanta. In algoritmul anterior, cel de-al treilea ciclu era folosit pentru a aduna la costul total costul stocarii cantitatilor de cascaval. In varianta optimizata, am schimbat sensul de parcurgere al variabilei $j$ si, in felul acesta, putem calcula pe parcurs o parte din costul de stocare. Practic, la inceputul fiecarei iteratii din cel de-al doilea ciclu, $cost_stocare$ retine costul stocarii cantitatiior de cascaval din lunile $j+1, .., i$, el trebuind actualizat doar cu costul de stocare din luna $j$.
Folosind observatia ca fiecare functie este minima pe cel mult un interval, putem folosi un arbore de intervale pentru a stoca in el semidrepte. Aceasta este o utilizare oarecum neobisnuita a unui arbore de intervale, dar vom vedea ca este foarte utila in cazul acestei probleme. Pseudocodul solutiei este urmatorul:
* $; calculeaza vectorii SP si DP$
* $SP[ 0 ] = 0$
* $DP[ 0 ] = 0$
* $pentru i de la 1 la N$
** $SP[i] = SP[i-1] + S[i]$
** $DP[i] = DP[i-1] + D[i]$
* $; calculeaza vectorul cmin$
* $cmin[ 0 ] = 0$
* $pentru i de la 1 la N$
** $finit[i] = cmin[i-1] + F[i]$
** $P[i] = C[i] - SP[i-1]$
** $[li,ri] = find_interval(i) ; gaseste intervalul [li,ri] pe care functia fi este minima$
** $daca intervalul [li, ri] nu este vid$
*** $update(li, ri, i, radacina_arborelui_de_intervale)$
** $cmin[i] = get_min(i) ; determina valoarea minima in punctul i dintre toate functiile existente$
* $suma = 0$
* $pentru i de la 1 la N$
** $suma = suma + SP[i-1] * D[i]$
* $afisaza cmin[N] + suma$
==code(c) |
; calculeaza vectorii SP si DP
SP[ 0 ] = 0
DP[ 0 ] = 0
pentru i de la 1 la N
SP[i] = SP[i-1] + S[i]
DP[i] = DP[i-1] + D[i]
; calculeaza vectorul cmin
cmin[ 0 ] = 0
pentru i de la 1 la N
finit[i] = cmin[i-1] + F[i]
P[i] = C[i] - SP[i-1]
[li,ri] = find_interval(i) ; gaseste intervalul [li,ri] pe care functia fi este minima
daca intervalul [li, ri] nu este vid
update(li, ri, i, radacina_arborelui_de_intervale)
cmin[i] = get_min(i) ; determina valoarea minima in punctul i dintre toate functiile existente
suma = 0
pentru i de la 1 la N
suma = suma + SP[i-1] * D[i]
afisaza cmin[N] + suma
==
Cele $3$ functii a caror implementare mai trebuie descrisa in detaliu sunt: $find_interval$, $update$ si $get_min$.
Pseudocodul pentru calculul capatului stanga al intervalului in care functia fi este minima este urmatorul:
* $*find_interval(i)*$
* $left=i$
* $right=N$
* $li=N+1$
* $cat timp left <= right$
** $mid = (left+right)/2$
** $fi_mid_1 = finit[i]+(DP[mid]-DP[i-1])*P[i] // valoarea in punctul DP[mid+1]$
** $fi_mid_2 = finit[i]+(DP[mid + 1]-DP[i-1])*P[i] // valoarea in punctul DP[mid]$
** $fmin1=get_min(mid+1) // valoarea minima in punctul DP[mid+1]$
** $fmin2=get_min(mid) // valoarea minima in punctul DP[mid]$
** $df1 = fi_mid_1 - fmin1;$
** $df2 = fi_mid_2 - fmin2;$
** $daca (df1 < 0)$
*** $li = mid;$
*** $right = mid - 1;$
** $altfel$
** $daca (df1 - df2 > 0)$
*** $left = mid + 1;$
** $altfel$
*** $right = mid - 1;$
* $; la sfarsit, in li se afla capatul stanga al intervalului in care fi este minima (sau N+1 daca nu exista un astfel de interval)$
==code(c) |
find_interval(i)
left=i
right=N
li=N+1
cat timp left <= right
mid = (left+right)/2
fi_mid_1 = finit[i]+(DP[mid]-DP[i-1]) P[i] // valoarea in punctul DP[mid+1]
fi_mid_2 = finit[i]+(DP[mid + 1]-DP[i-1]) P[i] // valoarea in punctul DP[mid]
fmin1=get_min(mid+1) // valoarea minima in punctul DP[mid+1]
fmin2=get_min(mid) // valoarea minima in punctul DP[mid]
df1 = fi_mid_1 - fmin1;
df2 = fi_mid_2 - fmin2;
daca (df1 < 0)
li = mid;
right = mid - 1;
altfel
daca (df1 - df2 > 0)
left = mid + 1;
altfel
right = mid - 1;
; la sfarsit, in li se afla capatul stanga al intervalului in care fi este minima (sau N+1 daca nu exista un astfel de interval)
==
Functiile $update$ si $get_min$ se aplica arborelui de intervale si au complexitate $O(logN)$. Complexitatea functiei $find_interval$ este $O(log^2^N)$.
Nu exista diferente intre securitate.
Topicul de forum nu a fost schimbat.