You are on page 1of 47

Karim Guevara Puente de la Vega

kguevara72@gmail.com
UCSM, 2014
Tcnicas de Diseo de
Algoritmos
Agenda
Fuerza Bruta
Recursividad
Divide y Vencers
Programacin Dinmica
Problemas
De Decisin:
183287 es primo?
Cul es el mnimo de la
secuencia [7,8,32]?
De optimizacin:
Hallar el camino ms
corto entre Buenos Aires y
Beijing
Ordenar la secuencia:
[1,9,34,-2,6,28]

Elegir o proponer una solucin.
Fuerza Bruta
Probar todas las opciones.
Se recorre todo el universo de soluciones posibles.

for cand in generarCandidatos()
if esSolucion(cand)
return cand;
Recursividad
Recursividad
Un procedimiento que se llama a si mismo, se le conoce como
un algoritmo recursivo
Permite describir algoritmos de forma ms clara y concisa,
especialmente:
Problemas recursivos por naturaleza
P.e. un rbol de bsqueda binario (BST)
Todos los registros con llaves menores estn en el subrbol de la
izquierda
Todos los registros con llaves mayores estn en el subrbol de la
derecha.
Recursividad
El algoritmo para recorrer los registros en orden es como
sigue:
Visita el subrbol de la izquierda
Visita la raz
Visita el subrbol de la derecha
void InOrden(Node* root){
if (root != NULL){
InOrden(root->left);
cout<<root->data;
InOrden(root->right);
}
}
Recursividad
Se usa una pila para almacenar los datos usados en cada
llamada a un procedimiento que an no termino.
Todos los datos no globales van a la pila registrando el
estado actual del clculo
Cuando una activacin anterior prosigue, los datos de la pila
son recuperados
Recursividad
En el caso del recorrido inorden
Para cada llamada recursiva, el valor de root y la direccin de
retorno de la llamada recursiva son almacenadas en la pila.
Cuando encuentra root = NULL el procedimiento retorna para
quien lo llam utilizando la direccin de retorno que est en la
cima de la pila
Recursividad
Procedimientos recursivos introducen la posibilidad de
iteraciones que pueden no terminar.
Es fundamental que la llamada recursiva a un procedimiento P
este sujeta a una condicin B, la cual se torno no satisfecha en
algn momento.
Para demostrar que una repeticin termina, se define una
funcin f(x), siendo x el conjunto de variables del programa,
tal que:
f(x) 0 implicada en la condicin de fin
f(x) es decrementada en cada iteracin
Recursividad
No todo problema de naturaleza recursiva debe ser resuelto
con un algoritmo recursivo.
Tales programas son fcilmente transformables en una versin no
recursiva.
P.e. cuando no usar recursividad: clculo de los nmeros de
Fibonacci




El programa es extremadamente ineficiente.


int Fibonacci(int n){
if (n < 2)
return n;
else
return Fibonacci(n-1) + Fibonacci(n-2);
}
Recursividad
Versin iterativa






El programa tiene una complejidad O(n) y de espacio O(1).


int FibonacciIterativo(int n)
{
int f=0, i=1;
for(j=1; j<=n; j++)
{
f=f+i;
i=f-i;
}
return f;
}
Recursividad
Debemos evitar el uso de recursividad cuando existe solucin
obvia por iteracin
Comparacin de versiones recursivas e iterativas:


N 20 30 50 100
Recursiva 1 seg 2 min 21 das 10
9
aos
Iterativa 1/3 mseg mseg mseg 1.5 mseg
Divide y Vencers
Vamos por partes
- Jack el destripador
Divide y Vencers
Consiste en dividir el problema en partes menores,
encontrar soluciones para las partes y combinarlas
en una solucin global.


DV(x){
if (x es suficientemente pequeo) {
return algoritmo_especfico(x);
}
else {
descomponer x en {x
i
, , x
k
}
for i = 1 to k
y
i
DV(x
i
)
y recombinar (y
i
, , y
k
)
return y;
}
}
Multiplicacin de enteros grandes
P.e.:


Clsico

981
1234
3924
2943
1962
981
1210554


Orden(n
2
)
La Russe

981 1234 1234
490 2468
245 4936 4936
122 9872
61 19744 19744
30 39488
15 78976 78976
7 157952 157952
3 315904 315904
1 631808 631808
1210554
Multiplicacin de enteros grandes
P.e.:






Dados A*B, A es el multiplicando y B el multiplicador:
1) n/2 dig
zq
(A) * n/2 dig
izq
(B) y desp
Izq
(n dig
B
)
2) n/2 dig
izq
(A) * n/2 dig
der
(B) y desp
Izq
(n/2 dig
B
)
3) n/2 dig
der
(B) * n/2 dig
izq
(A) y desp
Izq
(n/2 dig
B
)
4) n/2 dig
der
(B) * n/2 dig
der
(B)
5) Sumar
Divide y Venceras

Multplicar Desplazar Resultado
1) 09 12 4 108....
2) 09 34 2 306..
3) 81 12 2 972..
4) 81 34 0 2754
1210554
Multiplicacin de enteros grandes
P.e.: dados X=12345678 y Y=24680135,
determinar X*Y








Dividir
X = 12345678 = xi * 10
4
+ xd /xi=1234, xd=5678
Y = 24680135 = yi * 10
4
+ yd /yi=2468, yd=0135


Combinar
X * Y = (xi * 10
4
+ xd) * (yi *10
4
+ yd)
= xi * yi * 10
8
+ (xi * yd+xd *yi) *10
4
+ xd *yd

Multiplicacin de enteros grandes
En general, si X y Y tiene n dgitos

X = xi * 10
n/2
+ xd
Y = yi * 10
n/2
+ yd

Por tanto:
X * Y = (xi * 10
n/2
+ xd) * (yi * 10
n/2
+ yd)
= (xi*yi) * 10
n
+ ((xi*yd) + (xd*yi)) * 10
n/2
+ (xd*yd)








Multiplicacin de enteros grandes




funcin multiplica (X,Y,n) {
if (P es pequeo) {
return X*Y;
}else{
Obtener xi, xd, yi, yd; // DIVIDIR
z1 = multiplica (xi, yi, n/2);
z2 = multiplica (xi, yd, n/2);
z3 = multiplica (xd, yi, n/2);
z4 = multiplica (xd, yd, n/2);
aux = suma(z2,z3); // COMBINAR
z1 = desplaza_izq(z1,n);
aux = desplaza_izq(aux,n/2);
z = suma(z1,aux);
z = suma(z,z4);
return z;
}
}
Multiplicacin de enteros grandes




funcin multiplica (X,Y,n) { eficiencia
if (P es pequeo) { O(1)
return X*Y; O(1)
}else{
Obtener xi, xd, yi, yd; O(n)
z1 = multiplica (xi, yi, n/2); T(n/2)
z2 = multiplica (xi, yd, n/2); T(n/2)
z3 = multiplica (xd, yi, n/2); T(n/2)
z4 = multiplica (xd, yd, n/2); T(n/2)
aux = suma(z2,z3); O(n)
z1 = desplaza_izq(z1,n); O(n)
aux = desplaza_izq(aux,n/2); O(n)
z = suma(z1,aux,z4); O(n)
return z; O(1)
}
}
Multiplicacin de enteros grandes
Tiempo de ejecucin:


El cuello de botella esta en el numero de
multiplicaciones de tamao n/2.
Se podr mejorar la eficiencia..?
Reducir el numero de multiplicaciones necesario



Multiplicacin de enteros grandes

funcin multiplicaDV (X,Y,n){
if (P es pequeo) {
return X*Y;
} else {
Obtener xi, xd, yi, yd; // DIVIDIR
s1 = suma(xi,xd);
s2 = suma(yi,yd);
p = multiplicaDV (xi, yi, n/2);
q = multiplicaDV (xd, yd, n/2);
r = multiplicaDV (s1, s2, n/2);
aux = suma(r,-p,-q); // COMBINAR
aux = desplaza_izq(aux,n/2);
p = desplaza_izq(p,n);
z = suma(p,aux,q);
return z;
}
}
Multiplicacin de enteros grandes

funcin multiplicaDV (X,Y,n){ eficiencia
if (P es pequeo) { O(1)
return X*Y; O(1)
} else {
Obtener xi, xd, yi, yd; O(n)
s1 = suma(xi,xd); O(n)
s2 = suma(yi,yd); O(n)
p = multiplicaDV (xi, yi, n/2); T(n/2)
q = multiplicaDV (xd, yd, n/2); T(n/2)
r = multiplicaDV (s1, s2, n/2); T(n/2)
aux = suma(r,-p,-q); O(n)
aux = desplaza_izq(aux,n/2); O(n)
p = desplaza_izq(p,n); O(n)
z = suma(p,aux,q); O(n)
return z; O(1)
}
}
Multiplicacin de enteros grandes

Mnimo y mximo
P.e.: encontrar el mayor y menor elementos de un
vector de enteros, A[1n], n 1.

void MayMin(int *A, int izq, int der, int &May, int &Min){
int med, May1, May2, Min1, Min2;
if(der izq <= 1)
if(A[izq] < A[der]){
May = A[der]; Min = A[izq];
}
else {
May = A[izq]; Min = A[der];
}
else
{
med = (izq + der) / 2;
MayMin(A, izq, med-1, May1, Min1);
MayMin(A, med, der, May2, Min2);
(May1 > May2)? May = May1 : May = May2;
(Min1 < Min2)? Min = Min1 : Min = Min2;
}
}
Divide y Vencers
Sea f(n) el nmero de comparaciones entre los elementos
de A
T(n) = 1 para n2,
T(n) = T( n/2) + T( n/2) + 1 para n>2,
Por tanto:


Entonces:
T(n) = 2 T(n/2) + 1
= 4 T(n/4) + 3
. .
. .
. .
= 2
i
T( n/2
i
) + 2
i
-1
1 si n<=2
2 T(n/2) +1 si n>2

T(n) =
Divide y Vencers

T(n) = 2
i
T( n/2
i
) + 2
i
-1

Para llegar al caso base: n/2
i
= 2 i=log
2
n/2

Reemplazando en T(n):

T(n) = 2
log
2
n/2


T(2) + 2
log
2
n/2


1
T(n) = n/2

+ n/2

-1
T(n) = n

1
T(n) = O(n)
Divide y Vencers
Caractersticas de los problemas
El problema se puede descomponer en otros del
mismo tipo que el original y de tamao mas pequeo
(formulacin recursiva).
Los subproblemas pueden resolverse de manera
independiente.
Los subproblemas son disjuntos, sin solapamiento.
La solucin final se puede expresar como
combinacin de las soluciones de los subproblemas.
Eficiencia de los Algoritmos Divide y
Vencers






Donde:
a nmero de subproblemas
n/b tamao de cada subproblema
g(n)-coste de descomponer el problema inicial y combinar las
soluciones, o de resolver un problema elemental.

Divide y Vencers
Aplicaciones
Algoritmo de busqueda binaria.
Algoritmos de ordenacion (Mergesort, Quicksort).
Problema de la seleccion (p.ej. mediana)
Exponenciacion rapida.
Multiplicacion de matrices: Algoritmo de Strassen.
Subsecuencia de suma maxima.
Par de puntos mas cercano.
Eliminacion de superficies ocultas.
Numero de inversiones (rankings).
FFT: Transformada Rapida de Fourier (convoluciones).
Interacciones entre n particulas.
Calendario de una liga
Programacin Dinmica
BB Einstein
Programacin Dinmica
Cuando la suma de los tamaos de los subproblemas
es O(n) entonces es probable que el algoritmo
recursivo tenga complejidad polinomial.
Cuando la divisin de un problema de tamao n
resulta en n subproblemas de tamao n-1 entonces es
probable que el algoritmo recursivo tenga
complejidad exponencial.
En ese caso, la tcnica de programacin dinmica
puede llevar a un algoritmo ms eficiente.
Programacin Dinmica
La programacin dinmica calcula la solucin para
todos los subproblemas, partiendo de los
subproblemas menores para los mayores,
almacenando los resultados en una tabla.
La ventaja es que una vez que un subproblema es
resuelto, la respuesta es almacenada en una tabla y
nunca ms es recalculado.
Programacin Dinmica
Clculo de la serie Fibonacci






El programa tiene complejidad O(n) y de espacio
O(n)
int FibonacciIterativo(int n)
{
int(*f = new int[n+1], fib;
f[0] = 0; f[1] = 1;
for(int i = 2; i>=n; i++)
f[i] = f[i-1] + f[i-2];
fib = f[n];
delete[] f;
return fib;
}
Ejemplo- Problema de la mochila
Un ladrn encuentra una caja fuerte llena de varios objetos
de diferentes tamaos y valores, pero tiene una mochila de
capacidad limitada; cual es la combinacin de objetos que
debe llevar para maximizar el valor del robo?
Ejemplo- Problema de la mochila
Se disponen de los siguientes objetos:
Objeto Peso Valor
1 1 15
2 5 10
3 3 9
4 4 5
Ejemplo- Problema de la mochila
Algoritmo:
w
i
representa el peso del objeto i
c
i
es el costo del objeto i
M es la capacidad de la mochila
n es el nmero de objetos.
B[i,w] es el mximo valor obtenido cuando se seleccionan
objetos de 1 a i y cuyo peso mximo no sobrepasa la
capacidad de la mochila, donde 0 i n y 0 w M
Ejemplo- Problema de la mochila

1 Data: w
1
w
2
w
n
, c
1
c
2
c
n

2 For w = 0 to M do
3 B[0,w] = 0;
4 End
5 For i = 0 to n do
6 B[i,0] = 0;
7 End
8 For i = 1 to n do
9 For w = 1 to M do
10 if w w
i
< 0 then
11 B[i,w] = B[i-1,w];
12 else
13 B[i,w] = max(B[i-1,w],c
i
+ B[i-1, w-w
i
];
14 end
15 end
16 end



Ejemplo- Problema de la mochila





1 Data: w
1
w
2
w
n
, c
1
c
2
c
n

2 For w = 0 to M do
3 B[0,w] = 0;
4 End
5 For i = 0 to n do
6 B[i,0] = 0;
7 End
8 For i = 1 to n do
9 For w = 1 to M do
10 if w w
i
< 0 then
11 B[i,w] = B[i-1,w];
12 else
13 B[i,w] = max(B[i-1,w],c
i
+ B[i-1, w-w
i
];
14 end
15 end
16 end



Ejemplo- Problema de la mochila
Para encontrar los items que fueron seleccionados hacemos
uso del algoritmo Backtrace
Data: B, w
1
w
2
w
n
, n, M
1 i n;
2 k M;
3 while i,k > 0 do
4 if B[i,k] B[i-1,k]then
5 X[i] 1 {item i esta en la mochila};
6 k k-w
i
;
7 i i-1;
8 else
9 i i-1;
10 end
11 end
Ejemplo- Problema de la mochila
Los valores de B[4,8] B[3,8] entonces el item 4 en la
mochila.







k = k w
4
= 8 4 = 4
Ejemplo- Problema de la mochila
Los valores de B[3,4] B[2,4] entonces el item 3 en la
mochila.







k = k w
3
= 4 3 = 1
Ejemplo- Problema de la mochila
Los valores de B[2,1] = B[1,1] entonces el item 2 no entra en
la mochila.







i = i 1 = 2 1 = 1
Ejemplo- Problema de la mochila
Los valores de B[1,1] B[0,1] entonces el item 1entra a la
mochila.







k = k w
1
= 1 1 = 0
Ejemplo- Problema de la mochila
Entonces la combinacin de objetos que maximizan el robo es:






Con la combinacin de los objetos 1,3 y 4 conseguimos llenar
la capacidad mxima de la mochila, as como obtener el
mayor lucro posible que es de 29.

You might also like