Você tem comprimentos arbitrários, não necessariamente integrais.
Cortando alguns palitos (um corte corta um palito, mas podemos cortar quantas vezes quisermos), você deseja obter palitos de tal forma que:
- Todos esses sticks têm o mesmo comprimento;
- Todos os sticks têm pelo menos o comprimento de todos os outros sticks.
Observe que obtemos sticks após a execução de cortes emC
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 ≥ 2
- Encomende as varas por ordem decrescente de comprimento, de forma que .
- 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 ... n
- 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 … n
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?
fonte
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 )L1≥L2≥⋯≥Ln O(nlogn)
Como @ user1990169 apontou, nunca precisamos cortar um pedaço .i≥k
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 )s 1≤s≤k 1,…,s k Ls 1,…,s−1 k Ls−1 O(klogk)
Se , esse valor é o tamanho ideal e podemos pular a fase dois.Ls−1=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 oo Ls−1>o≥Ls o>Ls o o
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 ii 1≤i≤s Ls ri j≤riLiLij j≤ri Lij<Ls−1
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 i ≤ 2 kO(klogk) ∑iri≤2k
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)
fonte
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 - 1Li L1,L2,...Li−1
Agora, desde , não faremos nenhum corte nos paus diante, pois sempre podemos ter paus com comprimento .L k k L kk<n Lk k Lk
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 - 1n k−1 k =k−1
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<k−1 k−1 (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 ik i j Lij L1
L1
A complexidade total do algoritmo acima éO(nlog(n)+k3)
fonte
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 ′ kk′ k′ k k′ k
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.
fonte