2010-10-07 13 views
5

Ho una collezione di numeri da 43 a 50 compresi tra 0,133 e 0,005 (ma principalmente sul lato piccolo). Vorrei trovare, se possibile, tutte le combinazioni che hanno una somma tra L e R, che sono molto vicini tra loro. *Problema di imballo dei contenitori (o dello zaino?)

Il metodo forza bruta richiede 2 a 2 gradini, che isn è fattibile Qual è un buon metodo da usare qui?

Modifica: le combinazioni verranno utilizzate in un calcolo e scartate. (Se stai scrivendo il codice, puoi presumere che siano semplicemente in uscita, io modifico se necessario.) Il numero di combinazioni sarà presumibilmente troppo grande per essere conservato in memoria.

* L = 0,5877866649021190081897311406, R = 0,5918521703507438353981412820.

+0

(2^50) nanosecondi = 13.0312489 giorni –

+0

Sì. Per ciascuna combinazione farò un calcolo sul numero e lo scarterei. – Charles

risposta

1

L'idea di base è convertirla in un problema di zaino intero (che è facile).

Scegliere un numero reale piccolo e e numeri tondi nel problema originale con quelli rappresentabili come k*e con numero intero . Più piccolo è e, più grandi saranno gli interi (compromissione dell'efficienza) ma la soluzione del problema modificato sarà più vicina a quella originale. Un e=d/(4*43) dove d è la larghezza dell'intervallo di destinazione dovrebbe essere abbastanza piccolo.

Se il problema modificato ha una soluzione esatta sommando al centro (arrotondato a e) dell'intervallo di destinazione, il problema originale ne ha uno da qualche parte nell'intervallo.

+1

Trovare una soluzione è un problema con lo zaino, ma la domanda chiede di trovarle tutte. – Aaron

+0

D'accordo, ma anche se ce ne sono davvero tanti (in media non ce ne saranno), allora almeno puoi generarli in modo efficace. –

1

Non ci hai fornito informazioni sufficienti. Ma sembra che tu sia nei guai se in realtà vuoi OUTPUT ogni possibile combinazione. Ad esempio, coerente con quello che ci hai detto che ogni numero è ~ .027. Se questo è il caso, allora ogni raccolta di metà degli elementi soddisfa il tuo criterio. Ma ci sono 43 scegli 21 di questi set, il che significa che devi produrre almeno 1052049481860 set. (troppi per essere fattibili)

Certamente il tempo di esecuzione non sarà migliore della lunghezza dell'output richiesto.

+1

+1 Questa è una prova valida. –

+0

E 50 scegliere 25 è di circa 126 trilioni ... :-) – Aaron

+0

Ma se si riesce a trovare un algoritmo che è O (la dimensione dell'output), quindi per problemi con solo un piccolo numero di set di soluzioni potrebbe essere interamente trattabile Quale sarebbe bello. Se l'input richiede un output molto grande, ovviamente hai ragione che ci vorrà molto tempo, ma probabilmente è il problema del chiamante. –

0

In realtà, c'è un modo più veloce intorno a questo:

(python)

sums_possible = [(0, [])] 
# sums_possible is an array of tuples like this: (number, numbers_that_yield_this_sum_array) 
for number in numbers: 
    sums_possible_for_this_number = [] 
    for sum in sums_possible: 
     sums_possible_for_this_number.insert((number + sum[0], sum[1] + [number])) 
    sums_possible = sums_possible + sums_possible_for_this_number 

results = [sum[1] for sum in sums_possible if sum[0]>=L and sum[1]<=R] 

Inoltre, Aaron è giusto, quindi questo può o non può essere fattibile per voi

+0

Questo non va bene perché sums_possible cresce esponenzialmente. –

+0

Ho bisogno di generare tutte le combinazioni, ma non posso tenerle tutte in memoria alla volta. Il codice può essere modificato per emetterli mentre vengono calcolati, usando solo (diciamo) 1 GB di memoria? – Charles

+0

potresti fare alcuni piccoli miglioramenti, come 'sums_possible = [somma in sums_possible se sum <= R]' (rimuovendo somme già troppo alte) nel primo ciclo, ma non so quanto di un miglioramento sarebbe essere. A parte questo, non riesco a vedere cosa si può fare .. –

Problemi correlati