OBI 2023 - Fase 3 - Programação Nível Júnior
Se você quiser se preparar para a OBI, não deixe de conferir o Roteiro de estudos de informática, e também a página de informática do NOIC, com todos os nossos materiais.
Cabo de Guerra
Comentário escrito por Henrique Vianna
Conhecimento prévio necessário:
Para solucionar esse exercicio, basta checarmos todas as maneiras de separar os 6 integrantes em dois times, cada um com 3 pessoas. Digamos que escolhemos a tripla para compor um dos times. Então, para que haja impasse, devemos ter que , sendo par (caso for ímpar, é automaticante impossível obter-se um impasse). Para isso, basta fazermos três fors, testando essa condição para todas as triplas ordenadas.
Clique aqui para conferir o código
Tesouro
Comentário escrito por João Pedro Castro
Conhecimento prévio necessário:
Começando pelo ponto dado iremos percorrer a ilha seguindo as instruções dadas, e para fazer isso podemos criar uma função que recebe como parâmetro a linha e coluna que estamos e retorna o resultado da busca. A lógica da função é a seguinte:
- Se estamos no X: ótimo, chegamos! Retorne o total de passos .
- Se esse quadrado já foi visitado: sabemos que existe um ciclo na ilha, e que nunca sairemos dele, pois já estivemos aqui e voltamos. Retorne 0.
- Marque esse quadrado como visitado.
- Calcule a próxima casa a ser visitada, chamaremos sua linha de e sua coluna de .
- Se ou M" /> ou ou M" />, ou seja, se o próximo quadrado for inválido: seremos jogados para fora da ilha. Retorne -1.
- Incremente em 1.
- Prossiga para a próxima casa.
E essa lógica vai passar, pois cada chamada da função tem complexidade de e chamaremos ela no máximo uma vez para cada quadrado, totalizando .
Clique aqui para conferir o código
Metrônibus
Em breve
Oficina Mecânica
Escrito por Caique Paiva
Conhecimentos prévio necessários:
Para esse problema, uma pessoa pode pensar em vários algoritmos gulosos diferentes, porém a maior parte deles dá errado, então, é importante que você saiba provar que algoritmos funcionam e saber construir exemplos que quebram um algoritmo. Vamos provar uma observação antes de construir o algoritmo. Primeiramente, defina uma permutação de de modo que, quando trocarmos 2 carros no mecânico, temos que , e além disso, a resposta do problema é minima.
Observação: Se e trocamos por , então .
Prova: Vamos olhar para um mecânico . Seja os carros que passaram por ele, nessa ordem. Veja que
- esperou 0 segundos para entrar
- esperou segundos para entrar
- esperou segundos para entrar.
- ...
- esperou segundos para entrar
Então, a somas dos segundos esperados para esse mecânico é , com isso, se P_j" /> com , então, podemos trocar eles dois de ordem, então conseguimos uma resposta menor, o que é um absurdo, pois essa é a resposta optimal, então sempre que .
Com isso, podemos supor que . Essa observação não é tão importante assim, a parte mais importante é que ela nos mostra a forma da resposta para cada mecânico, que é , com . Então, vamos tentar criar o algoritmo guloso colocando os carros no . Vamos olhar para o , qual mecânico queremos colocar ele?
Bem, como é maior que todos os outros elementos do vetor, temos que sua contribuição na resposta final vai ser nula, então podemos colocar ele em qualquer mecânico. Sendo mais geral, os últimos carros não contribuirão na resposta, então, seja o primeiro carro em qual colocar ele vai afetar nossa resposta, então, podemos escolher colocar ele no , assim aumentando nossa resposta em , ou então no , assim aumentando em , e assim vai. Veja que, gulosamente o optimal é pegar o tal que é minimo, e assim aumentando nossa resposta em !
Agora, vamos olhar para o . Dá mesma maneira do anterior, gulosamente, é melhor pegar o menor , mas se pegarmos o mesmo em que colocamos o , a nossa resposta vai aumentar em ao invés de só , portanto, só vale a pena pegar esse se ainda for menor que todos os outros . Vendo esses casos bases, é fácil de ver qual vai ser nosso algoritmo guloso.
Primeiro, vamos olhar para o nosso vetor em ordem decrescente. Seja V_2 > \cdots > V_n \} " /> o nosso vetor ordenado em ordem decrescente.
- Passo : Para cada mecânico , seja a quantidade de elementos que já colocamos nele. Então, vemos qual é o mínimo entre , seja ele . Adicionamos a nossa resposta , e aumentamos em 1.
Para calcular esses mínimos, podemos manter esses valores numa priority_queue, e então, a complexidade do problema fica .
Clique aqui para conferir o código