Non riesco a comprendere la soluzione di programmazione dinamica per il problema del partizionamento lineare. Sto leggendo il Algorithm Design Manual e il problema è descritto nella sezione 8.5. Ho letto la sezione innumerevoli volte ma non lo capisco. Penso che sia una spiegazione scarsa (quello che ho letto fino ad ora è stato molto meglio), ma non sono stato in grado di capire il problema abbastanza bene da cercare una spiegazione alternativa. Link a migliori spiegazioni benvenuto!Come comprendere la soluzione di programmazione dinamica nel partizionamento lineare?
Ho trovato una pagina con testo simile al libro (forse dalla prima edizione del libro): The Partition Problem.
Prima domanda: nell'esempio nel libro le partizioni sono ordinate dal più piccolo al più grande. È solo una coincidenza? Da quello che posso vedere l'ordinamento degli elementi non è significativo per l'algoritmo.
Questa è la mia comprensione della ricorsione:
Consente di utilizzare la seguente sequenza e la partizione in 4:
{S1...Sn} = 100 150 200 250 300 350 400 450 500
k = 4
Seconda domanda: Ecco come penso che la ricorsione avrà inizio - ho capito correttamente?
Il 1 ° ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 150 200 250 300 | 350 | 400 | 450 | 500 //done
Il 2 ° ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 150 200 250 | 300 350 | 400 | 450 | 500 //done
Il 3 ° ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 150 200 | 250 300 350 | 400 | 450 | 500 //done
Il 4 ° ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 150 | 200 250 300 350 | 400 | 450 | 500 //done
Il 5 ° ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 350 | 400 | 450 | 500 //1 partition to go
100 | 150 200 250 300 350 | 400 | 450 | 500 //done
Il 6 ° ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 | 350 400 | 450 | 500 //1 partition to go
100 150 200 250 | 300 | 350 400 | 450 | 500 //done
Il 7 ° ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 | 350 400 | 450 | 500 //1 partition to go
100 150 200 | 250 300 | 350 400 | 450 | 500 //done
L'8 ° ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 | 350 400 | 450 | 500 //1 partition to go
100 150 | 200 250 300 | 350 400 | 450 | 500 //done
Il 9 ricorsione è:
100 150 200 250 300 350 400 450 | 500 //3 partition to go
100 150 200 250 300 350 400 | 450 | 500 //2 partition to go
100 150 200 250 300 | 350 400 | 450 | 500 //1 partition to go
100 | 150 200 250 300 | 350 400 | 450 | 500 //done
ecc ...
Ecco il codice così come appare nel libro:
partition(int s[], int n, int k)
{
int m[MAXN+1][MAXK+1]; /* DP table for values */
int d[MAXN+1][MAXK+1]; /* DP table for dividers */
int p[MAXN+1]; /* prefix sums array */
int cost; /* test split cost */
int i,j,x; /* counters */
p[0] = 0; /* construct prefix sums */
for (i=1; i<=n; i++) p[i]=p[i-1]+s[i];
for (i=1; i<=n; i++) m[i][3] = p[i]; /* initialize boundaries */
for (j=1; j<=k; j++) m[1][j] = s[1];
for (i=2; i<=n; i++) /* evaluate main recurrence */
for (j=2; j<=k; j++) {
m[i][j] = MAXINT;
for (x=1; x<=(i-1); x++) {
cost = max(m[x][j-1], p[i]-p[x]);
if (m[i][j] > cost) {
m[i][j] = cost;
d[i][j] = x;
}
}
}
reconstruct_partition(s,d,n,k); /* print book partition */
}
Domanda sul dell'algoritmo:
- Cosa i valori vengono memorizzati nello
m
e nellod
? - Che cosa significa "costo"? È semplicemente il totale dei valori degli elementi all'interno di una partizione?O c'è qualche altro significato più sottile?
BTW, anche se non è possibile rispondere alle mie domande apprezzerei i commenti sulla qualità del materiale sorgente. Vorrei una conferma che non sono solo io a trovare la spiegazione scarsa (mi ha fatto sentire piuttosto stanca). –
Non penso che qui troverai molte persone in grado di rispondere alla tua domanda senza dare una spiegazione succinta del problema che devi risolvere. Ci sono molte varianti dei problemi di partizionamento e incollare lunghe tabelle dell'algoritmo che viene eseguito a mano non rende le cose più chiare. – hugomg