[Teoria] Bottom-up
In questo problema aiuterai Mourinho a rimettere il Chelsea di nuovo in pista. In particolare devi fare un algoritmo per comprare l'insieme di giocatori meno caro che formino un "buon team": la somma delle loro abilità dovrebbe avere una soglia di almeno \(T\). Nel nostro modello astratto assumiamo che ciascun giocatore è caratterizzato da un intero che rappresenta le sue abilità e da un prezzo del cartellino. La definizione formale del problema è la seguente
Input: Un insieme \( \{1,\ldots,n\} \) di \(n\) giocatori dove ciascun giocatore \(i\) è caratterizzato dai seguenti dati
1) \( s_i \geq 0 \) - un intero che descrive le sue skills
2) \( p_i \geq 0 \) - un intero che descrive il prezzo per acquistare \(i\).
In più è dato un intero non negativo \(T\) che è la somma richiesta di skills dei nuovi giocatori.
Output: Il costo più piccolo \(C\) tale che esiste un sottoinsieme \(P \subseteq \{1,\ldots,n \} \) di giocatori che soddisfano
\[ \sum_{i \in P} p_i = C \]
e
\[ \sum_{i \in P} s_i \geq T \]
a) Sia \( c[i,t] \) il costo minimale di una soluzione per l'istance (istanza?) che consiste nei primi \(i\) giocatori \( \{1,\ldots,i \} \) e che richiede come skills totale \(t\). In altre parole \( c[i,t] \) è il costo più piccolo tale che \(P \subseteq \{1,\ldots,i \} \) di giocatori che soddisfano
\[ \sum_{j \in P} p_j = c[i,t]\]
e
\[ \sum_{j \in P} s_j \geq t
\]
completa la relazione di ricorrenza per \( c[i,t] \) che può essere usata per la programmazione dinamica.
b) Scrivi un algoritmo in pseudocodice usando l'approccio bottom-up.
a) La mia relazione è questa
\[ c[i,t] =\left\{\begin{matrix}
\infty & \text{if} & t>0 \text{ and } i=0 \\
0 & \text{if} & t=0 \\
\min\{ p_i + c[i-1,t-s_i] , c[i-1,t] \} & &
\end{matrix}\right.
\]
Ora ho difficoltà ad implementare l'algoritmo
Sia \( p \) la lista dei prezzi e \(s\) la lista delle skills in ordine. Sia Team un sottoinsieme dei giocatori
Mourinho(p,s,T)
Input: Un insieme \( \{1,\ldots,n\} \) di \(n\) giocatori dove ciascun giocatore \(i\) è caratterizzato dai seguenti dati
1) \( s_i \geq 0 \) - un intero che descrive le sue skills
2) \( p_i \geq 0 \) - un intero che descrive il prezzo per acquistare \(i\).
In più è dato un intero non negativo \(T\) che è la somma richiesta di skills dei nuovi giocatori.
Output: Il costo più piccolo \(C\) tale che esiste un sottoinsieme \(P \subseteq \{1,\ldots,n \} \) di giocatori che soddisfano
\[ \sum_{i \in P} p_i = C \]
e
\[ \sum_{i \in P} s_i \geq T \]
a) Sia \( c[i,t] \) il costo minimale di una soluzione per l'istance (istanza?) che consiste nei primi \(i\) giocatori \( \{1,\ldots,i \} \) e che richiede come skills totale \(t\). In altre parole \( c[i,t] \) è il costo più piccolo tale che \(P \subseteq \{1,\ldots,i \} \) di giocatori che soddisfano
\[ \sum_{j \in P} p_j = c[i,t]\]
e
\[ \sum_{j \in P} s_j \geq t
\]
completa la relazione di ricorrenza per \( c[i,t] \) che può essere usata per la programmazione dinamica.
b) Scrivi un algoritmo in pseudocodice usando l'approccio bottom-up.
a) La mia relazione è questa
\[ c[i,t] =\left\{\begin{matrix}
\infty & \text{if} & t>0 \text{ and } i=0 \\
0 & \text{if} & t=0 \\
\min\{ p_i + c[i-1,t-s_i] , c[i-1,t] \} & &
\end{matrix}\right.
\]
Ora ho difficoltà ad implementare l'algoritmo
Sia \( p \) la lista dei prezzi e \(s\) la lista delle skills in ordine. Sia Team un sottoinsieme dei giocatori
Mourinho(p,s,T)
C and empty array of array of dimension nT
for i = 0 to n
c[i,0] = 0
end
for t = 1 to T
c[0,t] = infty
end
for t=1 to T
for i= 1 to n
c[i,t] <- infty
if t- s[i] >= 0
if c[i-1, t] >= c[i-1,t-s[i] ] + p[i]
c[i,t] <- p[i] + c[i-1,t-s[i] ]
else
c[i,t] <- c[i-1,t]
else if t- s[i] < 0
if c[i-1, t] >= c[i-1,0] + p[i]
c[i,t] <- p[i] + c[i-1,0 ]
else
c[i,t] <- c[i-1,t]
end
end
return c[n,T]
Risposte
Qui sotto c'e' il codice che dovrebbe fare quello che hai implementato.
In questi esercizi, per avere vita lunga e preservare la salute mentale, ti consiglio di usare un linguaggio di programmazione reale, tipo il C, che poi non e' molto diverso da uno pseudo codice, e di imparare ad usare un debugger.
Lo pseudo codice va bene quando di fianco hai la maestra che legge e controlla quello che hai fatto.
Ad esempio qui c'e' un debugger C online con gia' il codice pre-caricato.
https://onlinegdb.com/xHyesZJtP
In questi esercizi, per avere vita lunga e preservare la salute mentale, ti consiglio di usare un linguaggio di programmazione reale, tipo il C, che poi non e' molto diverso da uno pseudo codice, e di imparare ad usare un debugger.
Lo pseudo codice va bene quando di fianco hai la maestra che legge e controlla quello che hai fatto.
Ad esempio qui c'e' un debugger C online con gia' il codice pre-caricato.
https://onlinegdb.com/xHyesZJtP
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#define N 3
#define INFINITY 1000000000
int p[N] = {3, 6, 4};
int s[N] = {2, 3, 7};
int cost(int i, int t){
printf ("%*c inizio cost con i = %d, t = %d \n", N-i, ' ', i, t);
if (t <= 0) {
printf("%*c t <= 0, return 0 \n", N-i, ' ');
return 0;
}
if (i < 0) {
printf("%*c i < 0, return inf \n", N-i, ' ');
return INFINITY;
}
int a, b;
printf("%*c chiamo cost con scelta giocatore \n", N-i, ' ');
a = p[i] + cost(i - 1, t - s[i]);
printf("%*c totale costo con scelta giocatore: %d \n", N-i, ' ', a);
printf("%*c chiamo cost senza scelta giocatore \n", N-i, ' ');
b = cost(i - 1, t);
printf("%*c totale costo senza scelta giocatore: %d \n", N-i, ' ', a);
if (a < b) {
printf("%*c return a: %d\n", N-i, ' ', a);
return a;
} else {
printf("%*c return b: %d\n", N-i, ' ', b);
return b;
}
}
int main()
{
int c;
c = cost(2, 5);
printf("costo minimo: %d\n", c);
return 0;
}
Grazie mille, a dire la verità io so un po' di Java, C++ e MatLab. Però l'esame sarà su carta e il prof richiede pseudocodice.
@Quinzio: Il programma che hai scritto non rispetta le condizioni dell'esercizio (per quanto condivida la preferenza nell'usare linguaggi reali piuttosto che finti e mal definiti). La tua soluzione segue un approccio top-down (invece che bottom-up) e non è un approccio di programmazione dinamica. Hai infatti semplicemente convertito la definizione del costo in una funzione ricorsiva che calcola più volte la stessa cosa.
Per un approccio bottom-up dobbiamo costruire la soluzione partendo dalle soluzioni costanti e calcolare gli altri valori a partire da questi. Qualcosa come il seguente insomma:
EDIT: Ho modificato il tuo codice per usare un metodo bottom-up: https://onlinegdb.com/U_XlWlIQ1
Per un approccio bottom-up dobbiamo costruire la soluzione partendo dalle soluzioni costanti e calcolare gli altri valori a partire da questi. Qualcosa come il seguente insomma:
C = D = {[0] 0, [t in 1 .. T] INFINITY }
for i in 1 .. N
D[0] = 0
for t in 1 .. (s[i] - 1)
D[t] = min(C[t], p[i])
for t in 1 .. T
D[t] = min(C[t], p[i] + C[t - s[i]])
swap(C, D)
result = C[T]
EDIT: Ho modificato il tuo codice per usare un metodo bottom-up: https://onlinegdb.com/U_XlWlIQ1