Anda di halaman 1dari 17

Cartilla de Solución de Problemas Problemas

ACM - ICPC - Latin America


2006

06 Septiembre del 2009

Esta cartilla contiene 9 problemas; las páginas están numeradas del 1 al 16

por:

Rayner Montes Condori


Julio Cesar Mendoza

Escuela Profesional de Ingenierı́a de Sistemas

Arequipa-Peru
1

Problema A
Weekend Lottery
Nombre del archivo fuente: lottery.c, lottery.cpp ó lottery.java

1.1. Resumen
El problema nos habla acerca de una loteria casera que se lleva entre estudiantes de una universi-
dad, en donde un estudiante elije C números de 1 hasta K (C y K son enteros) y depues los viernes
la loteria casera saca sus propios números y dependiendo de cuanto coinciden con los números que
saco el estudiante es que este gana el premio,Bueno algunos estudiantes no estan conformes con esta
forma de loteria es por eso que el problema consiste en dadas N loterias sacar como resultudo cual
o cuales números se han repetido menos veces en esas N loterias.

1.2. Entrada
La entrada contiene varios casos de prueba. La primera lı́nea de un caso de prueba contiene 3
enteros N (1 ≤ N ≤ 10000) y C (1 ≤ C ≤ 10) y K(C ≤ K ≤ 100) los cuales indican respectivamente
el número de loterias que ya han sucedido, la cantidad de números que se pueden escoger y el máximo
valor que se puede escoger. Cada una de las siguientes N lı́neas contienen C distintos enteros Xi
indicando el número de loterias en fechas anteriores (1 ≤ Xi ≤ k para 1 ≤ i ≤ C). El final de la
entrada esta indicado con N = C = K = 0.

1.3. Salida
Para cada caso de prueba, su programa deberá imprimir una sola lı́nea, conteniendo el conjunto
de números han salido menos veces en las N loterias. Este conjunto deberá ser imprimido como una
lista, en orden ascendente.

1.4. Solución
La estrategia consiste en construir un nuevo arreglo de enteros T de tamaño K, e inicializando
todo los elementos del arreglo en 0 (por comodida vamos a pensar que el arreglo comienza en el
ı́ndice 1), luego leer cada una de las N lı́neas ponerlas y al leer un número lo tomamos como ı́ndice
del arreglo T e incrementamos su contenido en 1 por ejemplo si leemos en una lı́nea el número 3,
nos vamos al T [3] y sumamos 1 a su contenido, y asi sucesivamente con los demas números, una
vez hecho esto procedemos a buscar en el arreglo T el minimo elemento min, al hallarlo, buscamos
una vez mas en el arreglo T todos los ı́ndices que tienen a min y lo añadimos a un nuevo arreglo G
finalmente imprimimos G.

1.4.1. Análisis en Tiempo


El costo de este algoritmo se ve claramente influenciado por la busqueda secuencial del mı́nimo
elemento en el arreglo T lo cual se hace dos veces por lo que el costo de este algoritmo es de Θ(K)(K
elementos)

1
2

1.4.2. Análisis en Espacio


El costo espacial de este algoritmo debido a la creación del arreglo T es de θK a este se le puede
sumar el arreglo G que cuyo pero caso seria cuando todos los elementos de T sean iguales. Pero de
igual forma esto no cambiarı́a que sea θK por obvias razones.

1.5. Correctitud

2
3

Problema B
Lazy Jumping Frog
Nombre del archivo fuente: frog.c, frog.cpp ó frog.java

2.6. Resumen
Sr. Rana vive en una grilla-pantano de forma rectangular, compuesta por celdas de igual tamaño,
algunos de las cuales están secas, y las otras con lugares con agua. Sr. Rana vive en una celda seca
y puede ir sólo de una celda seca a otra celda seca en sus viajes alrededor del pantano.
Sr. Rana quiere visitar a su novia, Sra. Sapo, quien tambien vive en una celda seca en el mismo
pantano. Pero Sr. Rana es flojo y quiere gastar la minima cantidad de energia en sus saltos camino
a la casa de Sra. Sapo. Sr. Rana conoce cuanta enrgia gasta para cualquiera de sus saltos. Para cada
uno de sus saltos Sr. Rana usa la siguiente figura para determinar las posibles celdas destino desde
su posicion actual y la energia gastada correpondiente al salto en calorias. Cualquier otra celda es
inalcanzable con un solo salto.

Tu tarea es determinar la minima cantidad de energia que MR. Frog necesita gastar para llegar
a la casa de la Sra. Sapo.

2.7. Entrada
La entrada contiene varios casos de prueba. La primera lı́nea de un caso de prueba consta de dos
números enteros, C y R, que indican el número de columnas y filas de los pantanos (1 ≤ C, R ≤ 1000).
La segunda lı́nea de un caso de prueba consta de cuatro enteros Cf , Rf , Ct , yRt , donde (Cf , Rf )
especificar el Sr. Ubicación de inicio de rana y (Ct , Rt ) especificar la ubicación casa de la Sra. Sapo
(1 ≤ Cf, Ct ≤ Cy1 ≤ Rf , Rt ≤ R). La tercera lı́nea de un caso de prueba contiene un entero
W (0 ≤ W ≤ 1000) que indica el número de lugares acuáticos en el pantano. Cada una de las
siguientes lı́neas W contiene cuatro enteros C1 , R1 , C2 yR2 (1 ≤ C1 , C2 ≤ C, 1 ≤ R1, R2 ≤ R), que
describe un zona compuesto por celdas con agua cuyas coordenadas (x, y) son tan que C1 ≤ x ≤ C2
y R1 ≤ y ≤ R2 . El final de la entrada se indica por C = R = 0.

2.8. Salida
Para cada caso de prueba, su programa deberá imprimir una sola lı́nea, conteniendo el minimo
numero de calorias consumidas por Mr.

2.9. Solución
El enunciado del problema muestra claramente que el problema es del tipo Single Shortest-Path.
Ya que las los pesos no pueden ser negativos usaremos el Algoritmo de Dijkstra para hallar el costo
del camino mas corto de F (ubicacion de la casa de Sr. Rana) a T(ubicacion de la casa de Sra. Sapo).

3
4

Los pesos de las aristas estaran determinados por:

 
7 6 5 6 7

 6 3 2 3 6 

B=
 5 2 0 2 5 

 6 3 2 3 6 
7 6 5 6 7
Ya que usaremos B en vez de la funcion peso debemos modificar el Algoritmo de Dijkstra:

Dijkstra(G, C, s, t)
1 for each vertex v ∈ V [G]
2 do C[v] ← ∞
3 C[s] ← 0
4 Q ← V [G]while Q 6= ∅
5 do u = ExtractM in(Q)
6 A = Adjs(u)
7 for i ← 1 to 5
8 do for j ← 1 to 5
9 do if Ai,j 6= nil and Ai,j 6= u and C[ Ai,j ] ≥ C[u] + Bi,j
10 then C[ Ai,j ] ← C[u] + Bi,j
11 return C[t]

Donde G es el grafo que representa la grilla, C es el arreglo que guarda los costos de los caminos
mas cortos de, s y t son los nodos origen y destino respectivamente. La funcion Adjs(u) devuelve
una matriz similar a B con referencias a los nodos adyacentes a u. Entre las lineas 7 a 10 relajamos
todos los nodos adyacentes.
LazyJumpingFrog(C, R, F, T, W )
1 G ← Make-Graph(C, R, W )
2 f ← Find-Node(G, F )
3 t ← Find-Node(G, T )
4 CT ← ∅
5 Dijkstra(G, CT, f, t)
6 if CT [t] = ∞
7 then return − 1
8 else return CT [t]

2.9.1. Análisis en Tiempo


El costo de Make-Graph (linea 1) es O(n) si usamos la representacion por listas de adyacencia. El
costo de Find-Node(lineas 2 y 3) es O(n) ya que podemos encontrar el cualquier nodo por inspeccion.
Dijkstra (linea 5) toma O(n log n) tiempo de ejecucion y el resto toma tiempo constante. El costo
del algoritmo es:
O(n log n) (2.1)

2.9.2. Análisis en Espacio


La estructuras adicionales presentes en el algoritmo son el heap del Algoritmo de Dijkstra, el
arreglo que guarda los costos y la matriz B, por ende el costo de espacio es:
O(n) (2.2)

4
5

2.10. Correctitud

5
6

Problema C
Bubble Maps
Nombre del archivo fuente: maps.c, maps.cpp ó maps.java

3.11. Resumen
Primero definimos que dada una región rectangular m, esta podemos dividirla en 4 partes iguales
por un corte horizontal y otro vertical. Los 4 cuatros subrectangulos formados vendrı́an a ser los
hijos de m que a su vez se llaman mp(dada en forma de String) para la región superior izquierda,
mq para la superior derecha, mr para la inferior derecha y ms para la inferior izquierda.
mp mq
ms mr
Una región puede ser varias veces dividida de la forma descrita, por ejemplo en la region mrs,
podemos subdividir a su hijo como se muestra en la figura de abajo:

msrpp msrpq msrqp msrqq


msrps msrpr msrqs msrqr
msrsp msrsq msrrp msrrq
msrss msrsr msrrs msrrr
Subregiones con nombre del mismo tamaño, se pueden decir que estan en el mismo nivel. Regiones
del mismo nivel que comparten un lado son llamados neighbors(vecinos).
El problema consiste en que dada una subregión debemos encontrar y determinar el nombre de
sus 4 neighbors.

3.12. Entrada
La entrada contiene varios casos de prueba. La primera lı́nea contiene un entero N indicando el
número de casos de prueba.Cada una de las siguientes N lineas corresponde a un caso de prueba
conteniendo en nombre de la región compuesta por C caracteres (2 ≤ C ≤ 5000), el primer caracter
siempre siendo ’m’ y las siguientes siendo ’p’, ’q’, ’r’ or ’s’.

3.13. Salida
Para cada caso de prueba, su programa deberá imprimir una sola lı́nea, conteniendo los nombres
de los 4 neighbors en el orden de dirección ARRIBA, ABAJO, IZQUIERDA, DERECHA, para los
neighbors que no estan en el mapa imprimir <none> en ves de su nombre. Dejar un espacio en blanco
entre dos nombres consecutivos.

3.14. Solución
Analizando el problema para el caso de la dirección ARRIBA, si tenemos una región y = xs (donde
x vendria a ser el padre de la región y y s un caracter cuyo significado lo dimos anteriormente) nos
damos cuenta que su neighbor hacia ARRIBA seria xp por la misma definición del problema en el
cual se dice como es la distribución de los nombres. Algo similar sucede con xr el cual su neighbor
seria xq. Por otro lado si la región fuera xp o xq la cosa cambia puesto que podria no tener un
neighbor hacia arriba ya que bien podria estar esa región en el lı́mite superior de la región completa,

6
7

por tal motivo recursivamente se mira al padre de y ya que este esta compuesto por los caracteres p
, q , r y s con un m al principio de la cadena. Luego se procede a hacer el mismo calculo anterior. Si
x vuelve a terminar en p o q, nuevamente recursivamente se mira al padre de x y asi sucesivamente.
Si al final resulta que nos quedamos tan solo con el caracter m significa que esa región no tiene
neighbor hacia ARRIBA y escribimos < none >, caso contrario al terminar la llamada recursiva le
aumentamos a la respuesta s o r segun haya sido p o q respectivamente.
Después aplicamos el mismo análisis para hallar los neighbors en las direcciones ABAJO, IZQUIER-
DA, DERECHA, y finalmente los mostramos como respuesta. Abajo mostramos el pseudocódigo de
la funcion principal y una de sus funciones auxiliares, las demas siguen la misma lógica:

Maps(N, R)
1 for i ← 1 to N
2 do P ← R[i]
3 Q ← Concat-Space(Arriba(P ), Abajo(P ), Izquierda(P ), Derecha(P ))
4 Print(Q)
5 return

Arriba(R)
1 L ← Length(R)
2 P adre ← SubCad(R, 1, L − 1)
3 U ltimo ← R[L]
4 switch
5 case U ltimo = ‘m0 :
6 resp ← “N ON E 00
7 case U ltimo = ‘p0 :
8 resp ← Arriba(P adre)
9 if resp 6= “N ON E 00
10 then resp = Concat(resp, ‘s0 )
11 case U ltimo = ‘q 0 :
12 resp ← Arriba(P adre)
13 if resp 6= “N ON E 00
14 then resp = Concat(resp, ‘r0 )
15 case U ltimo = ‘r0 :
16 resp = Concat(parent, ‘q 0 )
17 case U ltimo = ‘s0 :
18 resp = Concat(parent, ‘p0 )
19 return resp

3.14.1. Análisis en Tiempo


En cuanto al costo del algoritmo en tiempo primero definimos P como el tamaño de la cadena
ingresada, y como en el algoritmo el peor caso es que se llame P veces tanto en una o dos de las
funciones Arriba, Abajo, Izquierda o Derecha o máximo en dos de las funciones (suponiendo que la
región esta en una esquina) por lo tanto el costo del algoritmo serı́a θ(n), finalmente este algoritmo
es repetido N veces, pero N vendria a ser constante asi que el costo final del algoritmo es θ(n)

3.14.2. Análisis en Espacio


El costo en espacio es constante puesto que casi no se usa memoria auxiliar mas solo para unas
cuantas variables(ningun arreglo).

7
8

3.15. Correctitud

8
9

Problema D
Onion Layers
Nombre del archivo fuente: onion.c, onion.cpp ó onion.java

4.16. Resumen
Dr. Kabal, un biólogo y reconocido, ha descubierto recientemente un lı́quido que es capaz de
curar las enfermedades más avanzadas. El lı́quido se extrae de una cebolla muy rara que se puede
encontrar en un paı́s llamado Onionland. Pero no vale la pena llevar todas la cebollas al laboratorio
para su procesamiento. Solo las cebollas con un numero impar de capas contienen el liquido milagroso.

Figura 4.1: Puntos recopilados

Dr. Kabal ha contratado a una gran cantidad de asistentes de investigación para recopilar y
analizar las cebollas. Ya que no quiere compartir su descubrimiento con el mundo no le dijo a sus
asistentes que recogieran la cebollas con numero par de capas. En su lugar, a cada asistente se le dio
la tarea de recoger cebollas, y seleccionar puntos de cada una de las fronteras exteriores de la capa,
de modo que una aproximación de la estructura de capas de la cebolla se puede reconstruir después.
Dr. Kabal dijo a los asistentes que el próximo paso será un analisis complicado de estos puntos. De
hecho, lo único que hará es simplemente usar los puntos para contar el número de capas en cada una
de las cebollas, y seleccionar los que tienen un número impar de capas.

Figura 4.2: Aproximacion del Dr. Kabal

Tu tarea es ecribir un algoritmo que, dado un conjunto de puntos recolectados por los asistentes,
determines si tiene la cebolla será seleccionada.

4.17. Entrada
La entrada contiene varios casos de pruebla. La primera linea de un caso de prueba contiene un
entero N representando el numero de puntos recolectados (3 ≤ N ≤ 3000). Las siguientes N lineas
tendrán dos enteros X y Y tal que −2000 ≤ X, Y ≤ 2000. El final de la entrada esta indicado por
N = 0.

9
10

4.18. Salida
Para cada caso de prueba, su programa deberá imprimir una sola lı́nea, conteniendo:

Take this onion to the lab!


Si la cebolla debe seleccionarce ó

Do not take this onion to the lab!


Si la cebolla no debe seleccionarce.

4.19. Solución
El problema es determinar el numero de capas. Sea P el vector que contiene los puntos recopilados,
podremos determinar los puntos que pertenecen a la capa exterior hallando al cerradura convexa,
para hallar la capa subyacente eliminaremos los puntos que pertenecen a la capa exterior y volvere-
mos a hallar la cerradura convexa, este paso se repetira hasta que nos queden no menos de 3 puntos
(cantidad minima para formar una capa).

OnionLayers(P )
1 N ← length[P ]
2 Q←P
3 C←0
4 while |Q| ≥ 3
5 do L ← GrahamScan(Q)
6 Q←Q−L
7 C ←C +1
8 if C mod 2 = 1
9 then return true
10 else return f alse

4.19.1. Análisis en Tiempo


BOCETO:
EL costo del algoritmo esta determinado por las llamadas a GrahamScan cuyo costo es O(n log n), en
el peor de los casos la capas tendran 3 puntos cada una, por ende el numero de iteraciones sera n/3,
el costo de cada iteracion sera (n − 3 ∗ i) log(n − 3 ∗ i) donde 0 ≤ i ≤ n/3. El costo seria O(n2 log n).

4.19.2. Análisis en Espacio


La unica estructura de datos que empleada es la pila que usa GrahamScan para determinar la
cerradura convexa. Por ende el costo seria O(n)

4.20. Correctitud
Ya que el numero de elemntos de Q sera mayor que 3 en cada iteracion en que el contador C se
incremente se satisface la restriccion necesaria para que Graham’s scan sea correcto y garantizamos
que el numero de capas contadas sea correcta. El algoritmo termina verificando si el numero de capas
es impar.

10
11

Problema E
Odd or Even
Nombre del archivo fuente: Odd.c, Odd.cpp ó Odd.java

5.21. Resumen
El juego ”Pares y nones”para dos personas comienza cuando cada jugador escoje par o im-
par(non),a la cuenta de tres ambos levantan una de sus manos mostrando un numero de dedos(del 0
al 5). Si la suma de los dedos es par ganará el que haya escogido par, si la suma es impar ganará el
que haya escogido impar. Jhon y Mary juegan varias partidas de pares y nones, en cada partida Jhon
escoge impar y Mary escoge par. Ademas durante cada partida ambos anotan el numero de dedos
que muestran en cartas de diferente color(Jhon en cartas rojas y Mary en cartas azules). Al final del
dia se caen las cartas de Jhon y aunque puede separar las cartas por color, ahora estan desordenadas.
El objetivo es determinar el minimo numero de partidas que Mary pudo haber ganado.

5.22. Entrada
La entrada contiene varios casos de pruebla. La primera linea de un caso de prueba contiene un
entero N representando el numero de partidas jugadas (1 ≤ N ≤ 100) y. La segunda linea de un
caso de prueba contiene N enteros Xi, indicando el numero de dedos mostrado por Mary en cada
juego(0 ≤ Xi ≤ 5, para 1 ≤ i ≤ N ). La tercera linea contiene N enteros Y i, idicando el nuemro de
dedos mostrado por John in cada uno de los juegos (0 ≤ Y i ≤ 5, para 1 ≤ i ≤ N ). El final de la
entrada esta indicado por N = 0.

5.23. Salida
Para cada caso de prueba, su programa deberá imprimir una sola lı́nea, conteniendo el minimo
numero de veces que Mary a ganado.

5.24. Solución
Ya que Mary escogio par en cada partida, el minimo numero de partidas ganadas estaria deter-
minado por la permutacion de cartas rojas que obtenga la mayor cantidad de Y i tal que Xi + Y i sea
impar.
Si Mary muestra un numero impar de dedos y Jhon un numero par la suma sera impar.
Si Mary muestra un numero par de dedos y Jhon un numero impar la suma sera impar.
Si ambos muestran un numero par o impar de dedos la suma sera par.
Si agrupamos cada carta azul con numero impar con una carta roja con numero par obtendremos el
mayor numero de partidas que Jhon puede haber ganado, el resto de cartas azules(en caso de que las
cartas azules con numero impar sean mas que las rojas de numero par) o rojas(en caso contrario) se
agruparan con cartas de su mismo tipo(puesto que ya agrupamos las posibles) y corresponderá a las
que Mary pudo ganar.

OddOrEven(J, M )
1 N ← length[J]
2 C←0
3 for i ← 1 to N
4 do if Ji mod 2 = 1

11
12

5 then C ← C + 1
6 if Mi mod 2 = 0
7 then C ← C − 1
8 return abs(C)

Donde J y M son vectores que contienen el valor de las cartas rojas y azules respectivamente.

5.24.1. Análisis en Tiempo


El costo de algoritmo por el bucle (lineas 3 - 7) será O(N ) donde N el el numero partidas que
jugaron Jhon y Mary.

5.24.2. Análisis en Espacio


Ya que no usamos ninguna estructura adicional el costo es O(1)

5.25. Correctitud
Es evidente, ya que ambos tienen el mismo numero de cartas.

12
13

Problema F
Report Recovery
Nombre del archivo fuente: report.c, report.cpp ó report.java

6.26. Resumen
El problema básicamente consiste en dada una serie de lineas conteniendo cadenas de string no
espaciadas, a partir de ahi crear un reporte el cual debe tener sentido ya que ese reporte contiene tanto
nombres como números que deben de coincidir. Para lograr esto el problema nos da las siguientes
pistas:

La primera lı́nea se sabe que contiene el número de productos de la forma P 1 P 2... P N y la


cadena “Totals” al final.

Las siguientes lı́neas se sabe que comienzan con el nombre del vendedor(cadena) el stock que
vendió de cada producto y la suma total de productos que vendió.

La última lı́nea contiene la cadena “TP” seguida por la suma de los productos por columnas
de las lı́neas predecesoras

6.27. Entrada
La entrada contiene varios casos de prueba. La primera lı́nea de un caso de prueba contiene
los códigos de los productos tal como fue descrito arriba. El número de productos en esa linea es
consecutiva, de 1 a N , con (1 ≤ N ≤ 5). Luego las siguientes lı́neas representan una fila del reporte
como fue descrito arriba y la última lı́nea del reporte comienza con las letras T P y también tiene el
formato descrito arriba, considere que cada vendedor vende menos de 1000 unidades de cada producto,
no puede haber mas de 4 vendedores en cada caso. El nombre de cada vendedor no excedera los 10
caracteres.

6.28. Salida
Para cada caso de prueba, su programa deberá producir un posible reporte. Cada lı́nea deberá ser
alineada a la izquierda, con sus términos separados por un solo espacio y sin espacios al final de cada
lı́nea.

6.29. Solución
La estrategia consiste en:

Paso 1: Sacar de la primera lı́nea el número N de productos que hay y luego de las siguientes
lı́neas dividir la cadena en dos subcadenas, una conteniendo el nombre del vendedor y la otra
que contenga los números.

Paso 2: Dividir el tamaño de la cadena con números entre N + 1, para asi poder sacar los N
productos y su total

Paso 3: Aqui nos damos cuenta de que pueden haber muchas combinaciones de números pero
aprovechando las restricciones que nos puso el problema y ademas analizando que el número
de productos vendidos tiene que ser menor que la suma total de los productos en la fila(T ),

13
14

nos es posible crear las siguientes formulas, donde minCR y maxCR es el intervalo en donde
el tamaño de T (length(T )) variará.
mCR = length(lineaConN umeros)/(N + 1,0),
minCR = if (round(mCR) < mCR) then round(mCR) + 1 else round(mCR) y
maxCR = length(lineaConN umeros) - minCR − N + 1

Paso 4: En este punto probamos todas las combinaciones posibles que nos quedan y añadimos
en un array todas las posibles soluciones que se encuentren por cada lı́nea.

Paso 5: Se comprueba la solución con la última lı́nea en donde esta T P , si no es la correcta


se prueba otra combinacion hasta que una corresponda.

Paso 5: Imprimir el reporte.

6.29.1. Análisis en Tiempo


6.29.2. Análisis en Espacio

6.30. Correctitud

14
15

Problema G
Turkish Roulette
Nombre del archivo fuente: roulette.c, roulette.cpp ó roulette.java

7.31. Resumen
El problema nos dice que varios jugadores estan apostando en la ruleta Turka de un casino en
donde hay S casilleros los cuales estan numerados con valores que van desde -64 hasta 64 y B bolitas.
Cuando el distribuidor hace girar la ruleta los hombres tiran sus bolitas, y cuando esta para se ve que
cada bolita ocupa 2 casilleros, ahora bien, cada bolita tbn tiene un valor determinado y uno puede
ver la ganancia o perdida del distribuidor sumando los valores de los dos casilleros y multiplicando
el valor resultante con el valor de la bolita. Si el resultado es positivo el distribuidor pierde el monto
calculado, en caso contrario gana ese monto.
El problema consiste en determinar la mayor ganancia que un distribuidor puede tener dado un
número S de casilleros y un a lo mas bS/2c número de bolitas

7.32. Entrada
La entrada contiene varios casos de prueba. La primera lı́nea de un caso de prueba contiene
dos enteros S (3 ≤ S ≤ 250) y B (1 ≤ B ≤ S/2) los cuales indican respectivamente el número
de casilleros en la ruleta y el número de bolitas usadas. La segunda lı́nea de una prueba contiene
S enteros Xi (−64 ≤ Xi ≤ 64 por 1 ≤ i ≤ S) indicando el valor asociado a los casilleros de la
ruleta, en dirección de las agujas del relog. La tercera lı́nea de un caso de prueba contiene B enteros
Yi (−64 ≤ Yi ≤ 64 por 1 ≤ i ≤ S), indicando el valor asociado a las bolitas. El final de la entrada
esta indicado con S = B = 0.

7.33. Salida
Para cada caso de prueba, su programa deberá imprimir una sola lı́nea, conteniendo un entero
indicando la máxima ganancia que el Distribuidor puede ganar en un turno.

7.34. Solución
La estrategia consiste en meter todos los Xi y Yi en dos arrays X y Y respectivamente y con los
elementos del array X sumarlos de a pares en un array nuevo C y tanto C como Y los ordenamos
de menor a mayor, luego una variable M de tipo entero la inicializamos en 0. De ahi se presentan 3
casos...

Cuando Yi < 0 entonces este se multiplica con el mayor elemento de C y luego ambos elementos
sacarlos se eliminan y se le añade el monto calculado a M .

Cuando Yi == 0 aca simplemente eliminamos Yi

Cuando Yi > 0 entonces este se multiplica con el menor elemento de C y luego ambos elementos
sacarlos se eliminan y se le añade el monto calculado a M .

Roulette(S, B, X, Y )
1 for i ← 1 to S − 1
2 do C[i] ← X[i] + X[i + 1]

15
16

3 C[i] ← X[i] + X[1]


4 HeapSort(C)
5 HeapSort(Y )
6 j←1
7 k←S
8 M ←0
9 for p ← 1 to B
10 do if Y [i] = 0
11 then
12 M ← M + Y [i] ∗ C[j]
13 j ←j+1
14 else if Y [i] < 0
15 then
16 M = M + Y [i] ∗ C[k]
17 k ←k−1
18 return M

7.34.1. Análisis en Tiempo


En cuanto al costo del algoritmo básicamente serı́a el costo de ordenar los elemento del array con
lo que podemos usar un Merge-Sort o Heap-Sort con lo cual el costo final del algoritmo seria θ(N )

7.34.2. Análisis en Espacio


En cuanto al costo del espacio como usamos otro arreglo de tamaño S pues seria θ(S). Si no
queremos crear otro arreglo ps podemos hacerlo en el mismo arreglo X, pero tendriamos que usar
una variable auxiliar para guardar el X[1]

7.35. Correctitud
La correctitud de este algoritmo se demuestra porque al ordenar los elementos estamos garanti-
zando que cada elemento que cojamos sea el mayor de todos o el menor de ese modo uno puede sacar
el maximo producto ya que la multiplicacion de 2 numeros maximos resulta un número maximo lo
mismo pasa con la suma.

16

Anda mungkin juga menyukai