O desafio
Existem N cidades alinhadas em uma linha reta. A i-ésima cidade está localizada A[i]
quilômetros à direita da origem. Não há duas cidades no mesmo lugar.
Você vai construir uma rede elétrica com algumas usinas de energia. Usinas elétricas devem ser construídas dentro de uma cidade. No entanto, você só pode construir K
(<N) usinas de energia; portanto, haverá algumas cidades sem usinas de energia. Para cada cidade sem usinas de energia, você deve construir um cabo entre ela e a cidade mais próxima que possui uma usina .
Por exemplo, se houver três cidades localizadas em 0, 1, 2
e apenas a cidade 0
tiver uma usina, será necessário construir dois cabos, um de 2
até 0
(2 km) e outro de 1
até 0
(1 km), com um comprimento total de 3 km .
Dadas K
e posições das cidades ( A
), você deve calcular os quilômetros mínimos de cabo necessários para construir a grade.
Exemplos de casos de teste
K = 1, A = [0, 2, 4, 6, 8] : 12
# build power plant in the city at position 4, total length = 4 + 2 + 0 + 2 + 4 = 12
K = 3, A = [0, 1, 10, 11, 20, 21, 22, 30, 32] : 23
# build power plants in cities at positions 0, 10 and 22
K = 5, A = [0, 1, 3, 6, 8, 11, 14] : 3
# build power plants in all cities except those at positions 0, 3
K = 6, A = [0, 1, 3, 6, 8, 14, 15, 18, 29, 30, 38, 41, 45, 46, 49, 58, 66, 72, 83, 84] : 49
Especificações
Você deve implementar uma função ou um programa, que use um número inteiro positivo
K
e uma lista de números inteirosA
de qualquer forma, e gerar / retornar um número inteiro representando a resposta.A
é classificado em ordem crescente e todos os elementos são números inteiros não negativos.A[0] = 0
eA[N-1]
não ultrapassará 1000N.Observe que a saída será na magnitude de 1000N 2 ; portanto, em casos maiores, talvez seja necessário números inteiros de 64 bits em alguns idiomas.
Multithreading não é permitido (definirei a afinidade do seu programa como apenas 1 núcleo ao julgar). Otimizações de compilador (como
-O2
em C) são permitidas.
Pontuação
Eu cronometrarei seu código no meu computador (Ubuntu 16.04 com processador Intel i7-3770S) com diferentes tamanhos de caixas de teste. Especificamente, gerarei alguns casos de teste com N = floor (2 x / 5 ), em que x é um número inteiro positivo.
Sua pontuação será o valor x do menor caso de teste que seu programa usa mais de 10 segundos ou 1 GiB de memória ou não fornece uma resposta correta.- A resposta com maior pontuação vence. Se duas respostas obtiverem a mesma pontuação, a resposta anterior vence.
Todos os programas serão julgados pelo mesmo conjunto de casos de teste.
Sinta-se livre para postar suas próprias pontuações. Explicações do seu algoritmo são encorajadas.
Bônus
Este é o meu programa C ++, possui 108 . Você pode verificar o resumo do SHA-256 9a87fa183bad1e3a83d2df326682598796a216b3a4262c32f71dfb06df12935d
por todo o segmento de código (sem rodapé) no link.
O algoritmo combina a pesquisa binária e a otimização de Knuth para encontrar a penalidade correta de cada planta para obter o número desejado. A complexidade é O (N log N log A [N-1]). Fiquei surpreso que o programa obteve uma pontuação mais alta que a solução O (N log A [N-1]) de Anders Kaseorg . Provavelmente, é devido ao fato de que o caso do log na otimização de Knuth geralmente não ocorre.
Observe que esse desafio é o mesmo da IOI 2000 Post Office . As restrições originais são N <= 300 e K <= 30, no entanto.
fonte
2^^(x/5)
: qual é o significado ? você pode apenas fornecer um limite superior para N?N=21( = floor(2^(22/5)) )
em 10 segundos, mas não conseguirN=24( = floor(2^(23/5)) )
, 23 será a pontuação. Não usei um limite superior, pois as diferenças entre os diferentes algoritmos são grandes demais. Por exemplo, se eu definir N <= 40, haverá pouca diferença entreO(KN^2)
eO(KN^3)
, no entantoO(2^N)
, nem terminará em tempo razoável.Respostas:
Ferrugem , pontuação = 104
Esta é uma implementação do algoritmo observado por Grønlund et al. (2017) no final do §3.3.1, embora eu tivesse que seguir uma longa cadeia de citações e preencher alguns detalhes ausentes. É executado no tempo O ( N log A [ N - 1]).
Compile com
rustc -O
. O formato de entrada estáK
na primeira linha, seguido pelas entradas deA
, uma entrada por linha, todas em stdin.(Nota: estou enviando isso uma hora após o prazo final da recompensa, mas espero que a última versão que eu enviei antes do prazo final da recompensa , que foi executada no tempo O ( N log N log A [ N - 1]), tenha cerca de 94 .)
Experimente online!
Ferrugem , pontuação no pré-teste = 73
Compile com
rustc -O
. O formato de entrada estáK
na primeira linha, seguido pelas entradas deA
, uma entrada por linha, todas em stdin.Experimente online!
fonte
61
, mas isso ocorre por excesso deu32
. Talvez você possa mudar para o tipo inteiro de 64 bits?type Cost = u32
paratype Cost = u64
?73
.C, pontuação = 56
conteúdo de
a.c
:shell script para compilar e testar o acima:
n = 776 leva 6,2s, n = 891 leva 12sn = 1176 leva 5,9s, n = 1351 leva um pouco mais de 10sn = 1351 leva 8,7s, n = 1552 leva mais de 10s (com k = 2 * n / 3) no meu
Intel(R) Core(TM) i3-2375M CPU @ 1.50GHz
fonte
syntax/c.vim
.C ++, pontuação = 53
A solução que eu disse no comentário.
O(n²×k)
. (agora eu o apaguei porque não é mais necessário) Provavelmente pode ser reduzido paraO(n×k)
.A entrada é bastante flexível, na primeira linha, o primeiro número é
k
, os outros números são itens da matriza
, mas se encontrar parênteses próximos, ele interrompe a leitura da entrada. Portanto, entrada comoK = 1, A = [0, 2, 4, 6, 8] : 12
é aceita.Experimente online!
Gere casos de teste aleatórios. (entrada
N
e, opcionalmente, faixa de cidade,1000×N
por padrão)fonte
int
s necessários paraint64_t
s.C #, score = 23
Tenho certeza de que isso não vai vencer esse desafio, só queria postar uma primeira resposta (e muito básica) para incentivar outras pessoas a postar seus algoritmos e melhorar o meu. Esse código deve ser compilado como um projeto de console que usa o pacote Combinatorics do NuGet. O método principal contém algumas chamadas para o
Build
método para testar os casos propostos.Explicação realmente simples: para cada combinação
c
dek
elementos dea
, calcule a soma das distâncias de cada elemento dea
elemento mais próximoc
e retorne a combinação com a menor distância total.Versão de uma linha do
Build
método (provavelmente mais lenta que a versão expandida original; isso precisa incluir uma referênciaSystem.Linq
):fonte
C ++, pontuação = 48
Entrada de uso: NKA [1] A [2] ... A [N]
fonte
step
70, sua pontuação no pré-teste é 60.Ruby , pontuação = 23
Experimente online!
Eu não acho que vai ganhar, mas eu queria tentar.
fonte
JavaScript (ES6) (Node.js) , score = 10
Novo algoritmo, explicará se realmente funciona desta vez.
Experimente online!
Execute da mesma maneira que o outro.
JavaScript (ES6) (Node.js) , pontuação do pré-teste = 12
Esboço do algoritmo:
O programa primeiro mapeia os dados para a classe da cidade, que mapeia alguns pontos de dados:
a matriz é lançada na classe Group, que possui o seguinte:
Agora, o algoritmo divide os grupos desde que haja 2 ou mais usinas de energia.
Finalmente, ele mapeia os grupos para seus centros e resume todos eles.
Como executar:
Executar usando o Node.js (v9.2.0 é o que foi usado para a criação)
executando o programa usando casos de teste gerados para a pontuação 70:
executando o programa usando 1 usina e cidades [0,3,5]:
Código:
Experimente online!
Limparei o código comentado nos próximos dias, pois ainda estou trabalhando nisso, só queria ver se isso estava passando mais do que apenas nos pequenos casos.
fonte
K = 2, A = [0, 21, 31, 45, 49, 54]
. A resposta correta é 40, mas o seu programa gera 51.K = 2, A = [0, 4, 7, 9, 10]
. Correto: 7, sua resposta: 8.K = 2, A = [0, 1, 3, 4, 9]
. Correto: 6, sua resposta: 7.C (pontuação do pré-teste não concorrente = 76)
Esta é uma tentativa de traduzir a segunda solução Rust da @ AndersKaseorg para C.
Ajuntar com:
fonte
Limpo , pontuação = 65
Ajuntar com:
clm -h 1024M -gci 32M -gcf 32 -s 32M -t -nci -ou -fusion -dynamics -IL Platform main
Leva
K
e, em seguida, cada elemento deA
, como argumentos da linha de comando.fonte