Divisione equa di monete

di il
11 risposte

Divisione equa di monete

Salve a tutti!
Chiedo cortesemente aiuto per questo esercizio di algoritmi... premetto che lo sto studiando ora all'università, ma sto cercando di portarmi avanti con la materia e mi sono imbattuto in questo grattacapo.
Allora... chiede di determinare la differenza derivante dalla più equa divisione di un tot. di monete tra due persone in base al loro valore. Sia il numero di monete che i valori delle monete li prende da input, il numero di monete può essere al massimo 100 ed il valore delle monete delle monete varia da 1 e 500.

Es. 1 2 3 | differenza = 0
Es. 1 2 4 6 | differenza = 1

Inizialmente ho provato ad inserire i valori in una lista, ordinarla e poi da li partire con la distribuzione dalla moneta di più alto valore in giù, salvandomi le somme delle distribuzioni in due interi, in questo modo:
monete.sort();
suddivisione1 = 0;
suddivisione2 = 0;
differenza = 0;

while(!monete.empty()) {

monetaCorr = monete.back();
monete.pop_back();

if(differenza >= 0) {
differenza -= monetaCorr;
suddividisione1 += monetaCorr;
} else {
differenza += monetaCorr;
suddividisione2 += monetaCorr;
} // if.

} // while.

differenza = abs(differenza1 - differenza2);
Putroppo mi sono reso conto che non funziona sempre... ho provato a fare in un altro modo, funge, ma è troppo oneroso, cioè quello di generare tutte le possibili combinazioni di distribuzioni!
Quindi chiedo come posso renderlo più efficiente... leggendo un pò in giro, questo problema è tipico della programmazione golosa, spero di non sbagliarmi, ma non riesco ad applicarla! Grazie per l'attenzione!

11 Risposte

  • Re: Divisione equa di monete

    Non ho capito bene che intendi per differenza.

    Hai una cifra da dividere tra due o tre persone e questa è divisa in un numero di monete, quindi devi dare le monete alle tre persone cercando di dare un numero di monete uguali.
    E' corretto?
  • Re: Divisione equa di monete

    No, devo dividere il numero di monete tra le due persone in base ai loro valori, mi spiego meglio con quest'esempio:
    - ho 4 monete, di valori 1, 2, 4 e 6
    - dopo la distribuzione equa, uno avrà le monete 6+1 = 7, l'altro 2+4 = 6
    - la differenza derivata dalla distribuzione equa è uguale a 7-6 = 1
  • Re: Divisione equa di monete

    Si: un bel problema di ottimizzazione!
  • Re: Divisione equa di monete

    Penso che la soluzione per determinare quale sia quella ottima è fare un algoritmo ricorsivo con backtrack e pruning.
  • Re: Divisione equa di monete

    Non so come impostare il backtracking, non sono molto ferrato sull'argormento... sicuramente mi conviene partire da una buona base, cioè suddivido in due la lista di monete ordinata in ordine decrescente secondo questo algoritmo:
    
    		while(!monete.empty()) {
    
    			monetaCorr = monete.back();
    			monete.pop_back();
    
    			if(diff >= 0) {
    				sudd1.push_back(monetaCorr);
    				diff -= monetaCorr;
    			} else {
    				sudd2.push_back(monetaCorr);
    				diff += monetaCorr;
    			} // if.
    
    		} // for.
    
                    diff = abs(diff);
    
    Nella maggior parte dei casi mi basta far questo per avere l'equa distribuzione, però nel caso non succede, mi trovo con la differenza della divisione non ottima e dovrei in qualche modo provare tutti gli scambi possibili tra le monete delle due suddivisioni, andare avanti se trovo una differenza più bassa e tornare indietro se accade il contrario. Il problema è come farlo
  • Re: Divisione equa di monete

    Dovresti ragionare in questo modo.
    
    Funzione_assegna_monete(Lista monete, Persone ){
       Per tutti le persone a cui distribuire le monete{
              prendo una moneta e l'assegno a una persona
               /* ricorro */
               Funzione_assegna_monete(Lista monete, Persone );
               /* backtrack */
               rendo libera la moneta togliendola alla persona assegnata
        }
    }
  • Re: Divisione equa di monete

    Forse ho capito la tua idea e forse mi è venuta un'idea, anche se ho una perplessità... non c'è bisogno neanche che faccio la distribuzione tra le due persone, mi basta avere la lista delle monete e una lista dove metto le monete e con cui faccio ricorsione e backtracking con tutte le combinazioni di monete, tanto io so che la migliore differenza possibile è tra 0 e 1, cioè il risultato della mia divisione è uguale alla metà della somma dei valori di tutte le monete, quindi:
    - se raggiungo una divisione la cui somma supera quel valore, la scarto;
    - se la somma della divisione è uguale alla metà del valore di tutte le monete, allora mi posso fermare;
    - il problema è il caso peggiore... se la somma della mia divisione non raggiungerà mai la metà del valore di tutte le monete, il risultato finale è un minimo, ma per poterlo calcolare andrei a creare un albero con 2^n rami, cioè pari alle possibili combinazioni delle monete, giusto?
  • Re: Divisione equa di monete

    Io ti sono sincero ma i termini esatti del problema non l'ho capito.
    Ad ogni modo, mi pare debba distribuire in due o tre gruppi delle monete. Puoi estendere a un numero indefinito di gruppi.
    Adesso: la differenza dipende dal valore delle monete, se tu sai che è 0 o 1 non lo so. Comunque devi finire la distribuzione prima di scartare la soluzione. Puoi fermati se ne trovi una o puoi trovarle tutte se esistono.

    Quello che ti ho scritto è in pseudocodice il ragionamento della ricorsione con backtrak, si può immaginare il pruning per scartare e tagliare prima l'albero della ricorsione.

    P.s. se posti il testo completo dell'esercizio, con l'esempio di utilizzo, posso essere più puntuale nella risposta.
  • Re: Divisione equa di monete

    Io in realtà non so con sicurezza che la minima differenza tra la divisione sia 1 o 0, è una stima ottimistica che faccio facendo la somma dei valori delle monete, se è pari la migliore differenza possibile è 0, se è dispari è 1... è per darmi una condizione di fermata!

    Il testo cita: "Dato un sacchetto contenente un massimo di 100 monete, determinare la più equa
    divisione tra due persone. Ciò significa che la differenza tra il valore delle monete assegnate ad
    ogni persona dovrebbe essere minimizzato. Si suppone che il valore di una moneta varia da centesimo a 500 centesimi. Non è consentito suddividere una singola moneta."

    Ti faccio degli esempi:
    - ho M = {500, 1} quindi la differenza sarà (500) - (1) = 499
    - ho M = {1, 2, 3} quindi la differenza sarà (3) - (2+1) = 0
    - ho M = {1, 2, 4, 6} quindi la differenza sarà (6+1) - (6) = 1
    - ho M = {4, 7, 15, 21} quindi la differenza sarà (21+4) - (15+7) = 3

    Spero di essere stato chiaro!
  • Re: Divisione equa di monete

    Quindi la differenza la calcoli dopo aver distribuito le monete. Non è molto utile per fare il pruning dell'albero delle ricorsioni.

    Per cui se ho capito bene, le monete possono essere distribuite agli individui anche in numero diverso, purchè il valore sia il più equo possibile.

    Una precisazione: ci sono monete multiple di pari valore?
    Es: 2 moneta da 1, 1 moneta da 50, 3 monete da 20
  • Re: Divisione equa di monete

    Per cui se ho capito bene, le monete possono essere distribuite agli individui anche in numero diverso, purchè il valore sia il più equo possibile.
    Sisi, è proprio così.
    Una precisazione: ci sono monete multiple di pari valore?
    Es: 2 moneta da 1, 1 moneta da 50, 3 monete da 20
    Non lo specifica, ma credo che si possa considerare monete multiple.
    Credo che la soluzione potrebbe essere nella programmazione greedy
Devi accedere o registrarti per scrivere nel forum
11 risposte