Cortar varas iguais de varas diferentes

10

Você tem comprimentos arbitrários, não necessariamente integrais.n

Cortando alguns palitos (um corte corta um palito, mas podemos cortar quantas vezes quisermos), você deseja obter palitos de tal forma que:k<n

  • Todos esses sticks têm o mesmo comprimento;k
  • Todos os sticks têm pelo menos o comprimento de todos os outros sticks.k

Observe que obtemos sticks após a execução de cortes emCn+CC

Qual algoritmo você usaria para que o número de cortes necessários fosse mínimo? E qual é esse número?

Como exemplo, considere e qualquer . O seguinte algoritmo pode ser usado:n 2k=2n2

  • Encomende as varas por ordem decrescente de comprimento, de forma que .L1L2Ln
  • Se , corte a vareta nº 1 em duas partes iguais. Agora existem dois paus de comprimento , que são pelo menos contanto que os paus restantes .L 1 / 2 2 ... nL12L2L1/22n
  • Caso contrário ( ), corte a vareta nº 1 em duas partes desiguais dos tamanhos e . Agora existem dois manípulos de comprimento , que são maiores que e os outros manípulos .L 2 L 1 - L 2 L 2 L 1 - L 2 3 nL1<2L2L2L1L2L2L1L23n

Nos dois casos, um único corte é suficiente.

Tentei generalizar isso para maior , mas parece haver muitos casos a serem considerados. Você consegue encontrar uma solução elegante?k

Erel Segal-Halevi
fonte

Respostas:

6

A primeira observação central para resolver esse problema é que a viabilidade de um comprimento de corte ,l

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

é constante por partes, contínuo à esquerda e não aumenta em . Como o número de cortes necessários se comporta de maneira semelhante, encontrar o comprimento ideal é apenasl

l=max{lFeasible(l)} .

Além disso, como as outras respostas propuseram, todas as descontinuidades de salto têm o formato . Isso nos deixa com um problema discreto e unidimensional de busca, passível de busca binária (depois de classificar um conjunto finito de candidatos).Li/j

Observe, além disso, que precisamos considerar apenas o que é menor que o maior , já que esse sempre é viável. kLik

Então, limites diferentes em levam a algoritmos de eficiência diferente.j

  • k1jk resulta em um espaço de pesquisa de tamanho quadrático (em ),k
  • L i1jk/i em um (supondo que sejam classificados por tamanho decrescente) eLi
  • limites um pouco mais envolvidos em um linear.

Usando isso, podemos resolver o problema proposto em tempo e espaço .Θ ( n + k )Θ(n+klogk)Θ(n+k)

Uma observação adicional é que a soma em cresce em por para cada candidato "aprovado", contando duplicatas. Usando isso, podemos usar a seleção de classificação em vez da pesquisa binária e obter um algoritmo que é executado no tempo e no espaço , o que é ideal. l 1 L i / j Θ ( n )Feasiblel1Li/jΘ(n)

Encontre os detalhes em nosso artigo Algoritmos eficientes para divisão de vara sem inveja com menos cortes (por Reitzig e Wild, 2015).

Rafael
fonte
Como se vê, as idéias de nossa abordagem para cortar gravetos transitam para o problema mais geral ou a repartição (proporcional) , um problema de relevância prática; veja nosso pequeno artigo sobre isso .
Raphael
4

Como o @randomA sugeriu, procederemos em duas fases: primeiro encontramos o conjunto de palitos que serão cortados e, em seguida, minimizamos o número de cortes.

Como no caso especial da pergunta, classificamos / os bastões para que . Isso leva tempo . O ( n log n )L1L2LnO(nlogn)

Como @ user1990169 apontou, nunca precisamos cortar um pedaço .ik

Na primeira fase, empregamos uma pesquisa binária para encontrar o número , , para que as varas possam ser cortadas em pelo menos pedaços de tamanho (mais alguns pedaços menores) , mas os paus não podem ser cortados em pedaços de tamanho . Isso levará tempo .1 s k 1 , , s k L s 1 , , s - 1 k L s - 1 O ( k log k )s1sk1,,skLs1,,s1kLs1O(klogk)

Se , esse valor é o tamanho ideal e podemos pular a fase dois.Ls1=Ls

Caso contrário, sabemos que o tamanho ideal satisfaz e se então resulta do corte de pelo menos um dos paus em pedaços de tamanho igual. A fase dois determinará :L s - 1 > o L s o > L s o ooLs1>oLso>Lsoo

Para cada bastão , , determine um conjunto de tamanhos candidatos da seguinte maneira: Se cortar em pedaços de tamanho transformar o bastão em pedaços (incluindo o menor, se houver), os candidatos a esse stick são todos os valores , onde e . (Consulte a resposta de @ user1990169 para saber por que esses são os únicos tamanhos de candidatos.)1 i s L s r i L ii1isLsri jriLiLijjriLij<Ls1

Mantenha para cada tamanho de candidato, com que frequência ele ocorreu. Usando uma árvore de pesquisa balanceada, isso pode ser feito em , pois o número total de tamanhos de candidatos é vinculado por .i r i2 kO(klogk)iri2k

Agora, o tamanho do candidato que ocorre com mais frequência e leva a um corte válido é o que nos fornece a solução ideal. Além disso, se qualquer tamanho candidato levar a um corte válido, qualquer tamanho menor levará a um corte válido também.

Portanto, podemos empregar novamente a pesquisa binária para encontrar o maior tamanho de candidato que leva a um corte válido em . Em seguida, iteramos sobre o conjunto de comprimentos de candidatos até esse limite e encontramos o que possui a maior multidão entre eles em .O ( k )O(klogk)O(k)

No total, obtemos um tempo de execução em ou , se ignorarmos (ou não precisarmos fazer) a classificação inicial.O ( k log k )O(nlogn)O(klogk)

FrankW
fonte
Na etapa de busca binária, como exatamente você verifica se "as varas podem ser cortadas em pelo menos pedaços de tamanho "? k L s1,,skLs
Erel Segal-Halevi
Para computação . A soma desses valores é o número de peças que você pode obter. L i / L s1isLi/Ls
precisa saber é o seguinte
"o tamanho do candidato que ocorreu com mais frequência ... é o que nos dá a solução ideal" - por quê?
Erel Segal-Halevi
Como cada vez que ocorre, temos um pedaço de pau que dá pedaços com cortes . t - 1tt1
FrankW
11
O número total de cortes é na melhor das hipóteses ( varas de comprimento igual, todas as outras varas no máximo com a metade do comprimento dessas e, até onde eu posso ver, nunca serão maiores que . Definitivamente, nunca será mais do que , pois cada corte produz um pedaço do comprimento certo e um restante, mas parece que sempre podemos escolher um tamanho para que pelo menos um corte deixe um restante do comprimento correto. ter uma prova de que, embora). kk2 k-1kk2k1k
FrankW
1

Depois de ordenar os palitos na ordem decrescente de seus comprimentos, um palito será cortado apenas se todos os palitos tiverem sido cortados.G 1 , G 2 , . . . L i - 1LiL1,L2,...Li1

Agora, desde , não faremos nenhum corte nos paus diante, pois sempre podemos ter paus com comprimento .L k k L kk<nLkkLk

Portanto, agora, em vez de , estamos lidando apenas com sticks (possivelmente adicionando o -ésimo stick como um todo) e o número máximo de cortes que serão necessários no pior caso .k - 1 k = k - 1nk1k=k1

Além disso, se o número ideal de cortes for , deve haver pelo menos um conjunto de varas entre as varas que devem ser tomadas como um todo a partir de 1 vareta originalk - 1<k1k1 (em partes ou em 1 peça) , ou seja, nenhuma parte desse manípulo original deve ser deixada sem uso. Isso ocorre porque, pelo princípio do buraco do pombo , deve haver pelo menos 1 corte que deverá produzir mais de um bastão válido.

Em seguida, você pode realizar dois loops aninhados (ambos até ). O loop externo deve indicar o número do bastão cujas partes devem ser tomadas e o loop interno, o número de partes feitas desse bastão. Para cada tamanho verifique se você pode obter k sticks viáveis ​​cortando os sticks diante sequencialmente e, se puder, atualize os cortes mínimos necessários até o momento, se o número necessário atual for menor.i j L ikij
L1LijL1

A complexidade total do algoritmo acima éO(nlog(n)+k3)

Abhishek Bansal
fonte
1

A ideia de alto nível seria a busca binária.

O tamanho de cada um dos k sticks solicitados será pelo menos o menor e, no máximo, o maior. Por esse motivo, prosseguimos usando a pesquisa binária no tamanho do bastão do meio, veja qual número podemos obter, se esse for maior que o fornecido , sabemos que precisamos escolher um novo tamanho de candidato de referência. Então, passamos para o maior ou menor usando o novo stick de referência. Paramos quando é menor quek k k kkkkkk

Depois de encontrarmos o stick de referência apropriado, há um caso de canto em que precisaríamos refinar ainda mais o tamanho. Podemos classificar todas as varas cortadas pelo número de cortes nelas e pelo tamanho da vareta. Escolha aquele com o menor número de cortes e o menor tamanho. Reduza o número de cortes neste bastão em 1 e faça com que todos os sub-bastões sejam iguais. Esse será o novo tamanho de referência, verifique se esse novo tamanho pode levar a aceitável . Eu admito, não sei como limitar o tempo de execução neste caso.k

Felizmente, posso ver algo útil em outras respostas.

InformedA
fonte
2
Penso que a ideia básica da sua abordagem funcionará. Mas sua descrição do algoritmo não é clara o suficiente para ter certeza. Você poderia adicionar um pseudocódigo mais detalhado?
FrankW
@FrankW No entanto, não tenho muita certeza sobre o tempo de execução. Vou ver o que as outras pessoas têm, essa é uma pergunta interessante de se fazer.
InformedA