D DD Departamento I II Informtica A AA Aplicada Divide y vencers. 1. Mtodo. 2. Un ejemplo sencillo. 3. Complejidad del mtodo. 4. Ejemplo: El mximo subarray. 2 Divide y vencers. 1. Mtodo. 2. Un ejemplo sencillo. 3. Complejidad del mtodo. 4. Ejemplo: El mximo subarray. 3 Mtodo. 4 Divide y vencers. Dividir. El problema se divide en varios problemas similares de menor tamao. Resolver. Si los subproblemas son asumibles se resuelven. En caso contrario se vuelve a aplicar el mtodo. Combinar. Se combinan las soluciones de los subproblemas para obtener la solucin total. Esquema de tres etapas! 5 Divide y vencers. Caractersticas que deben cumplir los problemas para que se pueda aplicar esta tcnica: El problema se debe poder descomponer en otros similares pero ms pequeos. Los nuevos problemas deben ser disjuntos. Debe ser posible combinar las soluciones individuales para obtener la global. Mtodo. 6 Divide y vencers. procedure Divide_y_Vencers (P : problema) is begin if P es simple then Solucionar P; else Descomponer P en {P1, P2, ..., Pn}; Divide_y_Vencers (P1); Divide_y_Vencers (P2); . . . . . . . . . . . . . . . . . . . Divide_y_Vencers (Pn); Combinar las soluciones de {P1, P2, ..., Pn}; end if; end Divide_y_Vencers; Mtodo. 7 Divide y vencers. Mtodo. Hasta donde conviene subdividir el problema? Existir un umbral n 0 a partir del cul es ms rpido aplicar el algoritmo inmediato. El clculo de n 0 no es trivial y depende de la implementacin. Es habitual utilizar mtodos empricos para su determinacin. Algoritmo Imnediato n 0 n T (n) Algoritmo Div. y Venc. Divide y vencers. 1. Mtodo. 2. Un ejemplo sencillo. 3. Complejidad del mtodo. 4. Ejemplo: El mximo subarray. 8 Un ejemplo sencillo. 9 Divide y vencers. Problema: -23 1 14 2 31 3 -3 4 13 n-1 -2 n . . . . A : function Maximo (i, j : integer) return integer is max : integer := integer'first; begin for k in i .. j loop if A(k) > max then max := A(k); end if; end loop; return max; end Maximo; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ put ("Valor maximo:"); put (Maximo(A'first, A'last)); La solucin inmediata sera: Encontrar el valor mximo en un array de nmeros enteros." Un ejemplo sencillo. 10 Divide y vencers. Enfoque "divide y vencers": 1. Dividir el array en dos partes. 2. Hallar el mximo de cada parte. 3. Seleccionar el mayor de los dos. Se sigue aplicando de forma recursiva. Un ejemplo sencillo. 11 Divide y vencers. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin end Maximo; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ put ("Valor maximo:"); put (Maximo(A'first, A'last)); Un ejemplo sencillo. 12 Divide y vencers. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else end if; end Maximo; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ put ("Valor maximo:"); put (Maximo(A'first, A'last)); Un ejemplo sencillo. 13 Divide y vencers. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else med := (i + j) / 2; max_i := Maximo (i, med); max_d := Maximo (med+1, j); end if; end Maximo; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ put ("Valor maximo:"); put (Maximo(A'first, A'last)); Un ejemplo sencillo. 14 Divide y vencers. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else med := (i + j) / 2; max_i := Maximo (i, med); max_d := Maximo (med+1, j); if max_i > max_d then return max_i; else return max_d; end if; end if; end Maximo; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ put ("Valor maximo:"); put (Maximo(A'first, A'last)); Divide y vencers. 1. Mtodo. 2. Un ejemplo sencillo. 3. Complejidad del mtodo. 4. Ejemplo: El mximo subarray. 15 Complejidad del mtodo. 16 Divide y vencers. Problema Problema 1 Problema 2 Problema 3 Problema a Problema a-1 . . . T(n/b) + T(n/b ) + T(n/b) + . . . + T(n/b) + T(n/b) a T ( n / b ) T(n) Descomposicin del problema y combinacin de las soluciones O ( n k ) Complejidad del mtodo. 17 Divide y vencers. En general responder a esta ecuacin: a 1, b 2, k 0 T ( n ) = a T ( n / b ) + O ( n k ) a : Nmero de subproblemas en que se descompone. n/b : Tamao de cada nuevo subproblema. T ( n ) = O ( n k ), a < b k O ( n k log n ), a = b k O ( n log b a ), a > b k Cuya solucin es: Complejidad del mtodo. 18 Divide y vencers. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else med := (i + j) / 2; max_i := Maximo (i, med); max_d := Maximo (med+1, j); if max_i > max_d then return max_i; else return max_d; end if; end if; end Maximo; O ( 1 ) O ( 1 ) Complejidad del ejemplo sencillo: (Enfoque Divide y Vencers) Complejidad del mtodo. 19 Divide y vencers. function Maximo (i, j : integer) return integer is med, max_i, max_d : integer; begin if i=j then return A(i); else med := (i + j) / 2; max_i := Maximo (i, med); max_d := Maximo (med+1, j); if max_i > max_d then return max_i; else return max_d; end if; end if; end Maximo; T ( n / 2 ) T ( n / 2 ) Complejidad del ejemplo sencillo: (Enfoque Divide y Vencers) Complejidad del mtodo. 20 Divide y vencers. T ( n ) = 2 T ( n / 2 ) + O ( 1 ) a = 2 b = 2 k = 0 a > b k 2 > 2 0 2 > 1 Complejidad del ejemplo sencillo: (Enfoque Divide y Vencers) T ( n ) = a T ( n / b ) + O ( n k ) O ( n log b a ) = O ( n log 2 2 ) = O ( n ) Complejidad del mtodo. 21 Divide y vencers. function Maximo (i, j : integer) return integer is max : integer := integer'first; begin for k in i .. j loop if A(k) > max then max := A(k); end if; end loop; return max; end Maximo; Complejidad del ejemplo sencillo: (Enfoque Inmediato) O ( n ) Ambos mtodos tienen la misma complejidad. Divide y Vencers es ms lento por la recursividad. En este caso es mejor el Enfoque Inmediato. Divide y vencers. 1. Mtodo. 2. Un ejemplo sencillo. 3. Complejidad del mtodo. 4. Ejemplo: El mximo subarray. 22 Ejemplo: El mximo subarray. 23 Divide y vencers. "Dados varios nmeros que supondremos almacenados en un array, se trata de encontrar la secuencia de nmeros contiguos cuya suma sea mxima." Problema: 12 1 2 2 -3 3 -4 4 -9 5 8 6 A : 12 7 5 8 -6 9 1 10 8 6 12 7 5 8 La solucin sera: cuya suma es 25. Por ejemplo, dado: Si existe ms de una solucin, nos conformaremos con hallar una de ellas. Ejemplo: El mximo subarray. 24 Divide y vencers. -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 Una solucin inmediata: Ejemplo: El mximo subarray. 25 Divide y vencers. procedure Maximo_Subarray is . . . . . . . . . . . . . . begin max := integer'first; for i in A'range loop suma := 0; for j in i .. A'last loop suma := suma + A(j); if suma > max then max := suma; inf := i; sup := j; end if; end loop; end loop; put ("Indice inferior: "); put (inf); new_line; put ("Indice superior: "); put (sup); new_line; put ("Valor de la suma : "); put (max); new_line; end Maximo_Subarray; O ( n 2 ) Ejemplo: El mximo subarray. Divide y vencers. Enfoque "divide y vencers": Se divide el array en dos partes. 3 4 5 6 7 8 9 10 1 2 Pueden darse tres casos: 3 4 5 6 7 8 9 10 1 2 El subarray est totalmente en la parte izquierda. 3 4 5 6 7 8 9 10 1 2 El subarray est totalmente en la parte derecha. 3 4 5 6 7 8 9 10 1 2 El subarray atraviesa la divisin. Ejemplo: El mximo subarray. Divide y vencers. Si el subarray est completamente en uno de los lados, se puede resolver de forma recursiva, finalizando cuando el tamao sea de un slo elemento. -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 -3 3 -4 4 -9 5 8 6 12 7 5 8 -6 9 1 10 12 1 2 2 El mximo subarray estar formado por la unin del de mayor suma en el lado izquierdo y el de mayor suma del lado derecho. En el otro caso, el subarray tendr una parte en el lado izquierdo y otra en el derecho. Las partes se correspondern con uno de estos casos: Ejemplo: El mximo subarray. Divide y vencers. procedure Maximo_Subarray (E_inf, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . begin end Maximo_Subarray; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ Maximo_Subarray (A'first, A'last, inf, sup, max); Ejemplo: El mximo subarray. Divide y vencers. procedure Maximo_Subarray (E_inf, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . begin if E_inf = E_sup then S_suma := A(E_inf); S_inf := E_inf; S_sup := S_inf; else end if; end Maximo_Subarray; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ Maximo_Subarray (A'first, A'last, inf, sup, max); O ( 1 ) Ejemplo: El mximo subarray. Divide y vencers. procedure Maximo_Subarray (E_inf, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . begin if E_inf = E_sup then S_suma := A(E_inf); S_inf := E_inf; S_sup := S_inf; else med := (E_inf + E_sup) / 2; Maximo_Subarray (E_inf, med, inf_i, sup_i, max_i); Maximo_Subarray (med + 1, E_sup,inf_d, sup_d, max_d); Subarray_Comun (E_inf, med, E_sup, inf_c, sup_c, max_c); end if; end Maximo_Subarray; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ Maximo_Subarray (A'first, A'last, inf, sup, max); T ( n / 2 ) T ( n / 2 ) ? O ( 1 ) O ( 1 ) Ejemplo: El mximo subarray. Divide y vencers. procedure Maximo_Subarray (E_inf, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . begin if E_inf = E_sup then S_suma := A(E_inf); S_inf := E_inf; S_sup := S_inf; else med := (E_inf + E_sup) / 2; Maximo_Subarray (E_inf, med, inf_i, sup_i, max_i); Maximo_Subarray (med + 1, E_sup,inf_d, sup_d, max_d); Subarray_Comun (E_inf, med, E_sup, inf_c, sup_c, max_c); if max_i > max_d and max_i > max_c then S_suma := max_i; S_inf := inf_i; S_sup := sup_i; elsif max_d > max_i and max_d > max_c then S_suma := max_d; S_inf := inf_d; S_sup := sup_d; else S_suma := max_c; S_inf := inf_c; S_sup := sup_c; end if; end if; end Maximo_Subarray; _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ Maximo_Subarray (A'first, A'last, inf, sup, max); O ( 1 ) T ( n / 2 ) T ( n / 2 ) ? O ( 1 ) O ( 1 ) Ejemplo: El mximo subarray. Divide y vencers. procedure Subarray_Comun (E_inf, med, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . begin end Subarray_Comun; Ejemplo: El mximo subarray. Divide y vencers. procedure Subarray_Comun (E_inf, med, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . begin suma_izq := integer'first; suma_tmp := 0; for i in reverse E_inf .. med loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_izq then suma_izq := suma_tmp; S_inf := i; end if; end loop; end Subarray_Comun; O ( n ) Ejemplo: El mximo subarray. Divide y vencers. procedure Subarray_Comun (E_inf, med, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . begin suma_izq := integer'first; suma_tmp := 0; for i in reverse E_inf .. med loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_izq then suma_izq := suma_tmp; S_inf := i; end if; end loop; suma_der := integer'first; suma_tmp := 0; for i in med+1 .. E_sup loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_der then suma_der := suma_tmp; S_sup := i; end if; end loop; end Subarray_Comun; O ( n ) O ( n ) Ejemplo: El mximo subarray. Divide y vencers. procedure Subarray_Comun (E_inf, med, E_sup : in natural; S_inf, S_sup : out natural; S_suma : out integer) is . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . begin suma_izq := integer'first; suma_tmp := 0; for i in reverse E_inf .. med loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_izq then suma_izq := suma_tmp; S_inf := i; end if; end loop; suma_der := integer'first; suma_tmp := 0; for i in med+1 .. E_sup loop suma_tmp := suma_tmp + A(i); if suma_tmp > suma_der then suma_der := suma_tmp; S_sup := i; end if; end loop; S_suma := suma_izq + suma_der; end Subarray_Comun; O ( 1 ) O ( n ) O ( n ) Ejemplo: El mximo subarray. Divide y vencers. T ( n ) = 2 T ( n / 2 ) + O ( n ) Complejidad del enfoque Divide y Vencers: a = 2 b = 2 k = 1 T ( n ) = a T ( n / b ) + O ( n k ) O ( n 1 log n ) = O ( n log n ) T ( n ) = O (1) + O (1) + T (n / 2) + T (n / 2) + O ( ? ) + O (1) O (n) + O (n) + O (1) n T (n) n 2 n log n