Tagliare bastoncini uguali da bastoncini diversi


10

Hai stick di lunghezze arbitrarie, non necessariamente integrali.n

Tagliando alcuni bastoncini (un taglio taglia un bastoncino, ma possiamo tagliare tutte le volte che vogliamo), vuoi ottenere bastoncini in modo che:k<n

  • Tutti questi stick hanno la stessa lunghezza;k
  • Tutti i bastoncini sono lunghi almeno quanto tutti gli altri bastoncini.k

Si noti che otteniamo stick dopo aver eseguito i tagliCn+CC

Quale algoritmo useresti in modo tale che il numero di tagli necessari sia minimo? E qual è quel numero?

Ad esempio, prendi e qualsiasi . È possibile utilizzare il seguente algoritmo:n 2k=2n2

  • Ordinare le levette in ordine decrescente di lunghezza tale che .L1L2Ln
  • Se taglia lo stick n. 1 a due pezzi uguali. Ora ci sono due bastoncini di lunghezza , che sono almeno lunghi quanto i bastoncini rimanenti .L 1 / 2 2 ... nL12L2L1/22n
  • Altrimenti ( ), tagliare lo stick n. 1 a due pezzi disuguali delle dimensioni e . Ora ci sono due stick di lunghezza , che è più lungo di e gli altri stick .L 2 L 1 - L 2 L 2 L 1 - L 2 3 nL1<2L2L2L1L2L2L1L23n

In entrambi i casi, è sufficiente un singolo taglio.

Ho provato a generalizzare questo a più grande , ma sembrano esserci molti casi da considerare. Riesci a trovare una soluzione elegante?k

Risposte:


6

La prima osservazione fondamentale per risolvere questo problema è che la fattibilità di una lunghezza di taglio ,l

Feasible(l)=[i=1nLilk] ,

è costante a tratti, continua a sinistra e non crescente in . Poiché il numero di tagli necessari si comporta in modo simile, trovare la lunghezza ottimale è giustol

l=max{lFeasible(l)} .

Inoltre, come hanno proposto le altre risposte, tutte le discontinuità nel salto hanno la forma . Questo ci lascia con un discreto problema di ricerca unidimensionale suscettibile alla ricerca binaria (dopo aver ordinato un gruppo finito di candidati).Li/j

Nota inoltre che dobbiamo solo considerare che è più corto di quello grande, dal momento che quello è sempre fattibile. kLik

Quindi, limiti diversi su portano ad algoritmi di diversa efficienza.j

  • k1jk genera uno spazio di ricerca di dimensioni quadratiche (in ),k
  • L i1jk/i in uno linearitmico (supponendo che gli siano ordinati per dimensione decrescente), eLi
  • limiti leggermente più coinvolti in uno lineare.

Usando questo, possiamo risolvere il problema proposto in time e spazio .Θ ( n + k )Θ(n+klogk)Θ(n+k)

Un'ulteriore osservazione è che la somma in cresce in di per ogni candidato che "ha superato", contando i duplicati. Usando questo, possiamo usare la selezione dei ranghi invece della ricerca binaria e ottenere un algoritmo che gira nel tempo e nello spazio , che è ottimale. l 1 L i / j Θ ( n )Feasiblel1Li/jΘ(n)

Trova i dettagli nel nostro articolo Algoritmi efficienti per la divisione Stick senza invidia con il minor numero di tagli (di Reitzig e Wild, 2015).


A quanto pare, le idee del nostro approccio al taglio dei bastoncini si ripercuotono sul problema più generale o sulla ripartizione (proporzionale) , un problema di rilevanza pratica; vedere il nostro breve articolo su questo .
Raffaello

4

Come suggerito da @randomA, procederemo in due fasi: prima troviamo la serie di bastoncini che verranno tagliati e quindi ridurre al minimo il numero di tagli.

Come nel caso speciale della domanda, ordiniamo / denominiamo i bastoncini in modo che . Questo richiede tempo . O ( n registro n )L1L2LnO(nlogn)

Come ha sottolineato @utente1990169, non dobbiamo mai tagliare un pezzo .ik

Nella prima fase utilizziamo una ricerca binaria per trovare il numero , , in modo che i bastoncini possano essere tagliati in almeno pezzi della taglia (più alcuni pezzi più piccoli) , ma i bastoncini non possono essere tagliati in pezzi della dimensione . Questo richiederà tempo .1 s k 1 , , s k L s 1 , , s - 1 L s - 1 O ( k log k )s1sk1,,skLs1,,s1kLs1O(klogk)

Se , questo valore è la dimensione ottimale e possiamo saltare la seconda fase.Ls1=Ls

Altrimenti sappiamo che la dimensione ottimale soddisfa e se allora risulta dal taglio di almeno uno dei bastoncini in pezzi di uguali dimensioni. La fase due determinerà :L s - 1 > o L s o > L s o ooLs1>oLso>Lsoo

Per ogni stick , , determinare un set di dimensioni candidate come segue: Se il taglio in pezzi di dimensioni trasforma il bastone in pezzi (incluso quello più corto, se presente), quindi i candidati per questo stick sono tutti i valori , dove e . (Vedi la risposta di @ user1990169 per il motivo per cui queste sono le uniche dimensioni candidate.)1 i s L s r i L ii1isLsri jriLiLijjriLij<Ls1

Mantenere per ogni dimensione del candidato, quanto spesso si è verificato. Utilizzando un albero di ricerca bilanciato, ciò può essere fatto in , poiché il numero totale di dimensioni candidate è vincolato da .i r i2 kO(klogk)iri2k

Ora la dimensione del candidato che si è verificata più spesso e porta a un taglio valido è quella che ci offre la soluzione ottimale. Inoltre, se qualsiasi dimensione candidata porta a un taglio valido, anche una dimensione più piccola porterà a un taglio valido.

Quindi possiamo nuovamente utilizzare la ricerca binaria per trovare la lunghezza del candidato più grande che porta a un taglio valido in . Quindi ripetiamo l'insieme delle lunghezze dei candidati fino a questa soglia e troviamo quello con la più grande moltitudine tra loro in .O ( k )O(klogk)O(k)

In totale otteniamo un runtime in o , se ignoriamo (o non dobbiamo fare) l'ordinamento iniziale.O ( k registro k )O(nlogn)O(klogk)


Nella fase di ricerca binaria, come si controlla esattamente se "i bastoncini possono essere tagliati in almeno pezzi della taglia "? k L s1,,skLs
Erel Segal-Halevi,

Per compute . La somma di questi valori è il numero di pezzi che puoi ottenere. L i / L s1isLi/Ls
FrankW,

"la dimensione del candidato che si è verificata più spesso ... è quella che ci offre la soluzione ottimale" - perché?
Erel Segal-Halevi,

Perché ogni volta che si verifica, abbiamo un bastoncino che dà pezzi con tagli . t - 1tt1
FrankW,

1
Il numero totale di tagli è nel migliore dei casi ( stick di uguale lunghezza, tutti gli altri stick al massimo la metà di questi e per quanto posso vedere non saranno mai più di . sicuramente non sarà mai più di , poiché ogni taglio produce un bastoncino della lunghezza giusta e un resto. Sembra però che possiamo sempre scegliere una dimensione in modo che almeno un taglio lasci un resto della lunghezza corretta. avere una prova per questo, però.) kk2 k-1kk2k1k
FrankW

1

Dopo aver ordinato i bastoncini in ordine decrescente delle loro lunghezze, un bastoncino sarà tagliato solo se tutti i bastoncini sono stati tagliati.L 1 , L 2 , . . . L i - 1LiL1,L2,...Li1

Ora dal momento che , non avremo alcun taglio sugli stick poi, poiché possiamo sempre avere stick con lunghezza .L k k L kk<nLkkLk

Quindi ora invece di , abbiamo a che fare solo con bastoncini (eventualmente aggiungendo il -th stick nel suo insieme) e il numero massimo di tagli che saranno richiesti nel caso peggiore .k - 1 k = k - 1nk1k=k1

Inoltre, se il numero ottimale di tagli è , allora ci deve essere almeno una serie di stick tra quei stick che devono essere presi complessivamente da 1 stick originalek - 1<k1k1 (in parti o in 1 pezzo) , cioè, nessuna parte di quella levetta originale deve essere lasciata "non utilizzata". Questo perché, secondo il principio del buco di piccione , ci deve essere almeno 1 taglio che deve produrre più di 1 stick valido.

È quindi possibile condurre due loop nidificati per entrambi (entrambi fino a ). L'anello esterno deve indicare il numero dello stick cui devono essere prese tutte le parti e l'anello interno deve indicare il numero di parti di tale stick. Per ogni dimensione controlla se puoi ottenere k stick fattibili tagliando in sequenza gli stick avanti, e se puoi, allora aggiorna i tagli minimi richiesti finora se il numero corrente richiesto è inferiore.i j L ikij
L1LijL1

La complessità totale dell'algoritmo sopra èO(nlog(n)+k3)


1

L'idea di alto livello sarebbe la ricerca binaria.

La dimensione di ciascuno dei bastoncini k richiesti sarà almeno il bastoncino più piccolo e al massimo il più grande. Per questo motivo, procediamo utilizzando la ricerca binaria sulla dimensione dello stick medio, vedere quale numero possiamo ottenere, se questo è maggiore della data allora sappiamo che dobbiamo scegliere la nuova dimensione del candidato di riferimento. Quindi passiamo al più grande o più piccolo usando il nuovo stick di riferimento. Ci fermiamo quando è inferiore ak k k kkkkkk

Una volta trovato lo stick di riferimento appropriato, esiste un caso angolare in cui dovremmo perfezionare ulteriormente le dimensioni. Possiamo ordinare tutti i bastoncini tagliati in base al numero di tagli su di essi e alla dimensione del bastoncino. Scegli quello con il minor numero di tagli e la minima dimensione. Riduci il numero di tagli su questo stick di 1 e realizzando tutti gli stick secondari di questo uguale dimensioni. Questa sarà la nuova dimensione di riferimento, controlla se questa nuova dimensione può portare a accettabili . Lo ammetto, in questo caso non so come limitare il tempo di esecuzione.k

Spero di vedere qualcosa di utile da altre risposte.


2
Penso che l'idea di base del tuo approccio funzionerà. Ma la tua descrizione dell'algoritmo non è abbastanza chiara per essere sicura. Potresti aggiungere uno pseudocodice più dettagliato?
FrankW,

@FrankW Ma non sono troppo sicuro del tempo di esecuzione. Vedrò cosa hanno gli altri, questa è una domanda piuttosto interessante da porre.
Informato il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.