Maratona Doméstica da UDESC - maio/2008

Propaganda
Universidade do Estado Santa Catarina - UDESC
Departamento de Ciência da Computação - DCC
Maratona Doméstica de Programação – 2008-1
(Claudete)
2 de junho de 2008
Lembrete:
• É permitido consultar livros, anotações ou qualquer outro material impresso cópia durante a prova.
• A correção é automatizada, portanto siga atentamente as exigências da tarefa quanto ao formato da
entrada e saída de seu programa.
• Todos os problemas têm o mesmo valor na correção.
• Procure resolver o problema de maneira eficiente. Na correção, a eficiência também é levada em conta.
As soluções serão testadas com outras entradas além das apresentadas como exemplo dos problemas.
• Nas implementações, as entradas e as saídas conhecidas serão padrão (ler e escrever na saída padrão).
• Utilize o Clarification para dúvidas da prova. Opcionalmente, os juízes respondem, contudo, as respostas
são acessíveis a todos.
• Dica geral da prova: “Os últimos serão os primeiros”!
Agradecimentos
•
•
•
•
•
Parte desta prova foi elaborada por Wanderley Guimarães, coach dos times do IME-USP.
André Guedes, coach dos times do UFPR.
UDESC, DATASUL, Rede Globo, Google, Editora NOVATEC.
Ao pessoal do suporte da UDESC e o Grupo Colméia.
Ao DCC e demais anônimos que tornaram este evento uma realidade.
Próxima Doméstica (ainda sem nome): 30/08/2008 (sábado)
1
Rascunho:
2
Problema A: Recuperação
Arquivo: recuperacao.[c|cpp|java]
A nossa grandiosa Professora Cris no último aquecimento ficou conhecida como a grande maquiavélica do IME. Para quem não está a par do assunto, a digníssima professora exigiu que os alunos
formassem uma fila em ordem lexicográfica (pelo nome) com no máximo k permutações. Isto fez
com que muitos alunos nem sequer entrassem na sala para fazer a prova. No entanto, nesta seletiva
ela resolveu se redimir perante seus alunos, e resolveu aplicar um probleminha para recuperação.
Sua tarefa, mesmo não tendo sido reprovado, é dada uma sequência de n inteiros a1 , a2 , .., an ,
P
onde −30 ≤ aj ≤ 30 para j = 1, 2, .., n, imprima, se existir, um inteiro ak tal que ak = k−1
i=1 ai . Se
houver mais de um inteiro que satisfaça esta condição, imprima o que aparece primeiro na seqüência.
Cris: “Meninos, lembrem-se que a soma de nenhum número é zero! Tá?”
Entrada
A entrada é composta de diversas instâncias. A primeira linha de cada instância consiste em um
inteiro n (1 ≤ n ≤ 100) indicando o número de inteiros na linha seguinte devem ser processados.
A entrada termina com final de arquivo.
Saída
Para cada instância, você deverá imprimir um identificador Instancia k, onde k é o número da
instância atual. Na linha seguinte imprima o inteiro que satisfaça a restrição descrita acima. Caso não
exista tal inteiro imprima nao achei.
Após cada instância imprima uma linha em branco.
Exemplo de entrada
1
0
7
1 2 3 4 5 6 7
Exemplo de saída
Instancia 1
0
Instancia 2
3
3
Problema B: Quem vai ser reprovado?
Arquivo: placar.[c|cpp|java]
Prof. Wallywow da Universidade da Columbia Britânica está muito preocupado com a queda
do nível de atenção de seus estudantes. Ele já tentou várias técnicas mundialmente conhecidas para
incentivar os alunos a prestar atenção nas suas aulas e fazer as tarefas que ele passa para a turma: deu
nota para os alunos mais participativos, ofereceu chocolates aos alunos, levou seu karaokê e cantava
nas aulas etc. Como tais medidas não levaram a uma melhora no comparecimento às aulas (a idéia do
karaokê, inclusive, mostrou-se bastante infeliz. . . na segunda aula com karaokê a turma reduziu-se a
um aluno – que tinha problemas auditivos) ele teve uma brilhante idéia: faria uma competição entre
os alunos.
Prof. Wallywow passou um conjunto de problemas aos alunos, e deu um mês para que eles os
resolvessem. No final do mês os alunos mandaram o número de problemas resolvidos corretamente. A
promessa do brilhante didata era reprovar sumariamente o último colocado da competição. Os alunos
seriam ordenados conforme o número de problemas resolvidos, com empates resolvidos de acordo
com a ordem alfabética dos nomes (não há homônimos na turma). Isso fez com que alunos com nomes
iniciados nas últimas letras do alfabeto se esforçassem muito nas tarefas, e não compartilhassem suas
soluções com colegas (especialmente aqueles cujos nomes começassem com letras anteriores). Sua
tarefa neste problema é escrever um programa que lê os resultados dos alunos do Prof. Wallywow e
imprime o nome do infeliz reprovado.
Qualquer semelhança entre o Prof. Wallywow e o Prof. Carlinhos é mera coincidência.
Entrada
A entrada é composta de diversas instâncias. A primeira linha de cada instância consiste em um
inteiro n (1 ≤ n ≤ 100) indicando o número de alunos na competição. Cada uma das n linhas
seguintes contém o nome do aluno e o número de problemas resolvidos por ele. O nome consiste em
uma seqüência de letras [a-z] com no máximo 20 letras e cada time resolve entre 0 à 10 problemas.
A entrada termina com final de arquivo.
Saída
Para cada instância, você deverá imprimir um identificador Instancia k, onde k é o número da
instância atual. Na linha seguinte imprima o nome do infeliz reprovado.
Após cada instância imprima uma linha em branco.
Exemplo de entrada
4
cardonha 9
infelizreprovado 3
marcel 9
infelizaprovado 3
Exemplo de saída
Instancia 1
infelizreprovado
4
Problema C: Não é Mais um Joguinho Canadense!
Arquivo: contagem.[c|cpp|java]
O Canadá é um país muito frio. Em 8 meses por ano as temperaturas praticamente impedem que
as ruas sejam ocupadas por vida inteligente, restando apenas criaturas resistentes ao frio como alces,
ursos e canadenses1 . Nestes longos meses de inverno famílias buscam diversão em frente de suas
lareiras (ou, para as mais corajosas, ao redor de suas fogueiras). A família Smith, de Banff, inventou
o jogo que descrevemos a seguir.
A brincadeira começa com uma das crianças desenhando um diagrama com estados (representados
por bolinhas) ligados por transições (flechas ligando os estados). Cada transição tem uma letra e um
número associados. Podemos fazer diversos passeios neste diagrama, partindo de um estado inicio
caminhando por suas transições e terminando em um estado final. Um passeio forma uma palavra
(obtida da concatenação das letras das transições percorridas) e tem um custo (que é dado pelo produto
dos números destas transições). Exemplo. Considere o diagrama abaixo.
1b
1a
p
1b
2b
q
2a
Figura 1: Diagrama
Todos os passeios iniciam no estado p e terminam em q.
O passeio que segue pelas transições (p,1a), (p,1a), (p,1b) e termina no estado q forma
a palavra aab concatenando as letras de cada transição tem custo 1 (produto dos números destas
transições).
O passeio que segue pelas transições (p,1a), (p,1a), (p,1b), (q,2b) e termina no
estado q forma a palavra aabb e tem custo 2.
O jogo inventado pelo papai Smith era o seguinte. Depois de desenhar um diagrama como esse,
um dos membros da família falava uma palavra, e os outros deveriam descobrir a soma dos custos de
todos os passeios no diagrama que formam a palavra dada tais que iniciam no estado p e terminam no
estado q. No caso do exemplo do diagrama acima, se o Sr. Smith pedisse a palavra aba a resposta
deveria ser 2.
Entrada
A entrada é composta de diversas palavras (o diagrama é sempre o da figura). Cada instância é dada
por uma linha contendo uma palavra. Uma palavra é uma seqüência de letras [a,b] com no máximo
60 letras.
A entrada termina com final de arquivo.
Saída
Para cada instância, você deverá imprimir um identificador Palavra k, onde k é o número da
instância atual. Na linha seguinte imprima a soma dos custos.
Após cada instância imprima uma linha em branco.
1
He he he, brincadeirinha. . .
5
Exemplo de entrada
a
b
ab
ba
aaaa
bbbb
aabb
abbb
Exemplo de saída
Palavra 1
0
Palavra 2
1
Palavra 3
1
Palavra 4
2
Palavra 5
0
Palavra 6
15
Palavra 7
3
Palavra 8
7
6
Problema D: Collatz (3n + 1)
Arquivo:
collatz.[c|cpp|java]
Considere o seguinte algoritmo para gerar uma seqüência de números:
1. Inciando com um inteiro n: se n é par divide-se por 2
2. Se n for ímpar, multiplica por 3 e adiciona 1
3. Repetindo este processo para o novo valor de n, terminando quando n = 1
Por exemplo: 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
é uma conjectura (mas que não foi provada ainda), que este algoritmo sempre vai terminar com n = 1
para todo inteiro n < 1.000.000. Para uma entrada n, tamanho do ciclo de n é o número de números
gerados pelo algoritmos incluindo 1 e o próprio n. No exemplo acima o tamanho do ciclo de 22 é 16.
Dado quaisquer dois números i e j, você tem que determinar o maior tamanho do ciclo para todos os
número entre i e j, inclusive.
Entrada
A entrada deve consistir em uma série de pares de inteiros i e j, sendo um par por linha. Todos o
inteiros devem ser menor de 1.000.000 e maior do que 0.
1 10
100 200
201 210
900 1000
Saída
Para cada par de inteiros i e j, mostrar i, j na mesma ordem em que eles aparecem na entrada,
seguindo do maior tamanho do ciclo para todos os números entre i e j, inclusive. Esses três números
devem ser separados por um espaço e todos os três números em um linha e com uma linha de saída
para cada linha de entrada.
1 10 20
100 200 125
201 210 89
900 1000 174
7
Problema E: Romanes eunt domus?
Arquivo romanes.[c|cpp|java]
O Imperador da Roma antiga, Sírus Flavius Deunxarius queria montar uma nova representação
de números em seu reino – que depois ficou conhecido como os números romanos. Mas como havia
uma representação muito precária para milhões, ele resolveu criar um risco na letra para representar
os milhões. Em um problema no espaço tempo Sírus acabou caíndo no futuro – aproximadamente
daqui a 45 minutos próximo de Roma (dizem que ele caiu em um wormhole). Como ele não sabe
muito bem de computadores, ele precisa converter binário ou hexadecimal para números Romanos
para se situar melhor no mundo moderno. A sua tarefa é implementar um programa que realize esta
tarefa para o nosso viajante no tempo2 .
Arábico Romano Arábico Romano Arábico Romano Arábico Romano
1
I
10
X
90
XC
950
CML
2
II
15
XV
91
XCI
999
CMXCIX
3
III
20
XX
100
C
1000
M
4
IV
40
XL
500
D
5000
_V_
5
V
50
L
555
DLV
1000000
_M_
Entrada
A entrada consiste em um número N - binário puro ou um hexadecimal iniciado por x (“xis minúsculo”). O programa pára quando a entrada for zero. Com 0 < N < 10.000.000
xFB
11110100010011011001
111
x292
0
Saída
A saída consiste no número em Romanos equivalente.
CCLI
_M_DCLXV
VII
DCLVIII
2
Não se preocupe, ele só passará 2 dias no futuro e voltará pro seu tempo - ele tem problemas com wormholes.
8
Problema F: Sudoku
Arquivo: sudoku.[c|cpp|java]
O jogo de Sudoku espalhou-se rapidamente por todo o mundo, tornando-se hoje o passatempo
mais popular em todo o planeta. Muitas pessoas, entretanto, preenchem a matriz de forma incorreta,
desrespeitando as restrições do jogo. Sua tarefa neste problema é escrever um programa que verifica
se uma matriz preenchida é ou não uma solução para o problema. A matriz do jogo é uma matriz de
inteiros 9 × 9. Para ser uma solução do problema, cada linha e coluna deve conter todos os números
de 1 a 9. Além disso, se dividirmos a matriz em 9 regiões 3 × 3, cada uma destas regiões também deve
conter os números de 1 a 9. O exemplo abaixo mostra uma matriz que é uma solução do problema.
1
4
7
6
5
9
2
3
8
3
9
5
4
2
8
1
6
7
2
8
6
3
1
7
4
5
9
5
2
3
1
7
4
9
8
6
7
6
8
5
9
2
3
1
4
9
1
4
8
3
6
5
7
2
4
3
2
7
8
5
6
9
1
6
7
1
9
4
3
8
2
5
8
5
9
2
6
1
7
4
3
Entrada
São dadas várias instâncias. O primeiro dado é o número n > 0 de matrizes na entrada. Nas linhas
seguintes são dadas as n matrizes. Cada matriz é dada em 9 linhas, em que cada linha contém 9
números inteiros.
2
1
4
7
6
5
9
2
3
8
1
4
7
6
5
9
2
3
8
3
9
5
4
2
8
1
6
7
3
9
5
4
2
8
1
6
7
2
8
6
3
1
7
4
5
9
2
8
6
3
1
7
4
5
9
5
2
3
1
7
4
9
8
6
5
2
3
1
7
4
9
8
6
7
6
8
5
9
2
3
1
4
7
6
8
5
9
2
3
1
4
9
1
4
8
3
6
5
7
2
9
1
4
8
3
6
5
7
2
4
3
2
7
8
5
6
9
1
4
3
2
7
8
5
6
9
1
6
7
1
9
4
3
8
2
5
6
7
1
9
4
3
8
2
3
8
5
9
2
6
1
7
4
3
8
5
9
2
6
1
7
4
5
Saída
Para cada instância, imprima uma linha dizendo Instancia k, onde k é o número da instância
atual. Na segunda linha, seu programa deverá imprimir SIM se a matriz for a solução de um problema
de Sudoku, e NAO caso contrário. Imprima uma linha em branco após cada instância.
9
Instancia 1
SIM
Instancia 2
NAO
10
Problema G: Cofrinhos da Vó Vitória
Arquivo: cofre.[c|cpp|java]
Vó Vitória mantém, desde o nascimento dos netos Joãozinho e Zezinho, um ritual que faz a alegria
dos meninos. Ela guarda todas as moedas recebidas como troco em dois pequenos cofrinhos, um para
cada neto. Quando um dos cofrinhos fica cheio, ela chama os dois netos para um alegre almoço, ao
final do qual entrega aos garotos as moedas guardadas nos cofrinhos de cada um.
Ela sempre foi muito zelosa quanto à distribuição igualitária do troco arrecadado. Quando, por
força do valor das moedas, ela não consegue depositar a mesma quantia nos dois cofrinhos, ela memoriza a diferença de forma a compensá-la no próximo depósito.
Tarefa
Vó Vitória está cando velha e tem medo que deslizes de memória a façam cometer injustiças com
os netos, deixando de compensar as diferenças entre os cofrinhos. Sua tarefa é ajudar Vó Vitória,
escrevendo um programa de computador que indique as diferenças entre os depósitos, de forma que
ela não tenha que preocupar-se em memorizá-las.
Entrada
A entrada é composta de vários conjuntos de teste. A primeira linha de um conjunto de teste contém um número inteiro N , que indica o número de depósitos nos cofrinhos. As N linhas seguintes
descrevem cada uma um depósito nos cofrinhos; o depósito é indicado por dois valores inteiros J
e Z, separados por um espaço em branco, representando respectivamente os valores, em centavos,
depositados nos cofres de Joãozinho e Zezinho. O final da entrada é indicado por N = 0.
Saída
Para cada conjunto de teste da entrada seu programa deve produzir um conjunto de linhas na saída.
A primeira linha deve conter um identicador do conjunto de teste, no formato “Teste n”, onde n é
numerado seqüencialmente a partir de 1. A seguir seu programa deve escrever uma linha para cada
depósito do conjunto de testes. Cada linha deve conter um inteiro que representa a diferença (em
centavos) entre o valor depositado nos cofrinhos do Joãozinho e do Zezinho. Deixe uma linha em
branco ao final de cada conjunto de teste. A grafia mostrada no Exemplo de Saída, abaixo, deve ser
seguida rigorosamente.
Exemplo
Entrada:
3
20 25
10 5
10 10
4
0 5
12 0
0 20
17 1
0
Saída:
11
Teste 1
-5
0
0
Teste 2
-5
7
-13
3
Restrições
0 <= N <= 100 (N = 0 apenas para indicar o m da entrada)
0 <= J <= 100 (valor de cada depósito no cofre de Joãozinho)
0 <= Z <= 100 (valor de cada depósito no cofre de Zezinho)
12
Problema H: Estágio
Arquivo: estagio.[c|cpp|java]
Você conseguiu um estágio para trabalhar como programador na secretaria da sua escola. Como
primeira tarefa, Dona Vilma, a coordenadora, solicitou que você aprimore um programa que foi desenvolvido pelo estagiário anterior. Esse programa tem como entrada uma lista de nomes e de médias
finais dos alunos de uma turma, e determina o aluno com a maior média na turma. Dona Vilma
pretende utilizar o programa para premiar o melhor aluno de cada turma da escola. O programa
desenvolvido pelo estagiário anterior encontra-se no final deste enunciado (em C e C++).
Como você pode verificar, o programa na forma atual tem uma imperfeição: no caso de haver
alunos empatados com a melhor média na turma, ele imprime apenas o primeiro aluno que aparece
na lista.
Tarefa
Dona Vilma deseja que você altere o programa para que ele produza uma lista com todos os alunos
da turma que obtiveram a maior média, e não apenas um deles. Você consegue ajudá-la nesta tarefa?
Entrada
A entrada é constituída de vários conjuntos de teste, representando várias turmas. A primeira linha
de um conjunto de testes contém um número inteiro N (1 <= N <= 1000) que indica o total de
alunos na turma. As N linhas seguintes contêm, cada uma, um par de números inteiros C (1 <= C
<= 20000) e M (0 <= M <= 100), indicando respectivamente o código e a média de um aluno.
O final da entrada é indicado por uma turma com N = 0.
Saída
Para cada turma da entrada seu programa deve produzir três linhas na saída. A primeira linha deve
conter um identificador do conjunto de teste, no formato “Turma n”, onde n é numerado a partir
de 1. A segunda linha deve conter os códigos dos alunos que obtiveram a maior média da turma. Os
códigos dos alunos devem aparecer na mesma ordem da entrada, e cada um deve ser seguido de um
espaço em branco. A terceira linha deve ser deixada em branco. O formato mostrado no exemplo de
saída abaixo deve ser seguido rigorosamente.
Exemplo
Entrada:
3
1 85
2 91
3 73
5
12300 81
12601 99
15023 76
10111 99
212 99
0
Saída:
13
Turma 1
2
Turma 2
12601 10111 212
Restrições
0 <= N <= 1000 (N = 0 apenas para indicar o fim da entrada)
1 <= C <= 20000
0 <= M <= 100
Código em C
#include <stdio.h>
#define MAX_ALUNOS 1000
int main()
{
int i, indice_melhor, n;
int turma=1;
struct
{
int codigo, media;
} alunos[MAX_ALUNOS];
/* le numero de alunos da primeira turma */
scanf("%d", &n);
while (n > 0)
{
/* le dados dos alunos */
for (i = 0; i < n; i++)
scanf("%d %d", &alunos[i].codigo, &alunos[i].media);
/* procura aluno de maior media */
indice_melhor = 0;
for (i = 1; i < n; i++)
if (alunos[i].media > alunos[indice_melhor].media)
indice_melhor = i;
/* escreve resposta */
printf("Turma %d\n%d\n\n", turma++, alunos[indice_melhor].codigo);
/* le numero de alunos da proxima turma */
scanf("%d", &n);
}
return 0;
}
14
Código em C++
#include <iostream>
const int MAX_ALUNOS = 1000;
int main()
{
int i, indice_melhor, n;
int turma=1;
struct
{
int codigo, media;
} alunos[MAX_ALUNOS];
// le numero de alunos da primeira turma
cin >> n;
while (n > 0)
{
// le dados dos alunos
for (i = 0; i < n; i++)
cin >> alunos[i].codigo >> alunos[i].media;
// procura aluno de maior media
indice_melhor = 0;
for (i = 1; i < n; i++)
if (alunos[i].media > alunos[indice_melhor].media)
indice_melhor = i;
// escreve resposta
cout << "Turma " << turma++ << "\n";
cout << alunos[indice_melhor].codigo << "\n\n";
// le numero de alunos da proxima turma
cin >> n;
}
return 0;
}
15
Problema Z: Dobradura de Papel
Arquivo: dobradura.[c|cpp|java]
Se uma grande folha de papel é dobrada na metade, e então na metade outra vez e assim sucessivamente,
com todas as dobras paralelas então, existirá uma série de vincos (marcas de dobra) paralelas. Algumas apontando para cima, outras para baixo, dividindo o papel em fracões do comprimento original. Se o papel for
aberto apenas “meio caminho” em cada dobra, então dobra formará um ângulo de 90 graus. Então, (vista pela
borda) ela forma uma "curva dragão". Por exemplo, se quatro dobras sucessivas forem feitas a curva a seguir
será vista(note que não cruza ela mesma, mas dois cantos se tocam):
s
Figura 2: Desdobrando o papel
Escreva um programa para desenhar a curva que aparece após N dobras. A especificação exata da curva é a
seguinte: o papel inicialmente é plano, com a “borda inicial” à esquerda, se olhado de cima. A metade direita
é dobrada de forma que cobre a metade esquerda. Então, a metade direita da nova “folha dupla” é dobrado
sobre a metade esquerda, para formar uma folha de 4 camadas, e assim por diante, até N dobraduras. Então,
cada dobra é aberta de uma dobra de 180 graus para uma dobra de 90 graus. Finalmente o papel é olhado pela
borda para vermos a “curva dragão". Nesta vista, a única parte não modificada da folha original é o pedaço
contendo a “borda inicial” e esta parte está na horizontal, com a “borda inicial” na esquerda. Isto define a curva
de maneira única. Na figura acima, a “borda inicial” é a terminação esquerda da parte horizontal da curva no
canto inferior direito(marcada com o ’s’ de Start em Inglês). A partes horizontais deverão ser mostradas com
caractere sublinhado( “_” ), e as partes verticais deverão ser mostradas com o caráter “|”.
O arquivo de entrada consistirá de uma série de linhas, cada uma com um único número N (1 ≤ N ≤ 13).
O final das entradas será marcado por uma linha contendo um Zero.
O arquivo de saída consistirá de uma série de “curvas dragão", uma para cada valor de N na entrada. Sua
figura deve estar deslocada o mais a esquerda e acima possível. Note que para N grandes, a figura terá mais
de 80 caracteres de largura, o que parecerá confuso na tela. O padrão gerado para cada número diferente de
dobraduras terminará com um caractere ‘ˆ’.
Entradas
2
4
1
0
Saídas
|_
_|
^
_
_
|_|_| |_
_|
_|
|_|
^
_|
^
16
Download