Cap_9-10-11_2010

download Cap_9-10-11_2010

of 54

Transcript of Cap_9-10-11_2010

  • 5/21/2018 Cap_9-10-11_2010

    1/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    1

    Tcnicas Algortmicas.

    A continuacin estudiaremos algunas tcnicas generales para la construccin de algoritmos.Cada una de estas tcnicas tienen caractersticas especiales que las hacen apropiados pararesolver ciertos tipos de problemas. Desde luego una tcnica siempre podr tener algunaventaja o desventaja respecto de otra. Lo importante, en todo caso, es enfrentar

    medolgicamente la construccin de algoritmos que obedecen a ciertas estrategias. Sinembargo, debo insistir en que no se deberan aplicar estas tcnicas en forma indiscriminada acualquier problema. En general, la estructura del problema determina habitualmente la

    posibilidad de aplicacin de una tcnica especfica. Sin embargo, considerar que muchosproblemas pueden resolverse buscando una solucin fcil y directa pero, a la vez bastanteineficiente. Este mtodo, llamado de fuerza bruta, puede ser muy directo, pero con un poco deanlisis puede encontrarse algoritmos ms eficientes. El esquema mas sencillo quizs sea elllamado divide y vencers, basado en la descomposicin de un problema en subproblemas.Otros esquemas requieren un anlisis minucioso del problema de forma que la solucin sevaya construyendo en etapas. Si puede preverse que decisin conviene en cada etapa para

    producir cierto tipo de mejor resultado, tenemos una solucin voraz, si la decisin en una

    etapa, solo puede tomarse tras considerar varias soluciones de otras etapas mas simples, lasolucin es dinmica. Aun as, hay problemas cuya solucin no puede hallarse sino medianteun proceso de bsqueda, a pesar de lo complejas que son las operaciones de bsqueda, su usoadecuado mediante el esquema de bsqueda con retroceso (o backtracking) permite ganargran eficiencia respecto a soluciones de fuerza bruta. Por ultimo, conviene conocer otrosmtodos de diseo de algoritmos que tambin resultan de utilidad prctica. Otro no menosimportante, por la diversidad de campos de aplicacin es la programacin dinmica, muy tilen la asignatura de Investigacin de Operaciones, por ejemplo, en donde se utiliza el empleode tablas o arreglos matriciales como estructura auxiliar para la resolucin eficiente del

    problema. Las tcnicas que se abordan son:

    a) Fuerza Bruta,

    b) Divide y Vencers,

    c) Programacin Dinmica y

    d) Algoritmos Avidos (Greedy).

    e) Backtracking

    a) Fuerza Bruta

    Los algoritmos de Fuerza Bruta se caracterizan por una falta de sofisticacin en la solucin.En general, se toma la ruta ms directa, sin ningn intento de minimizar el nmero deoperaciones necesarias para calcular la solucin.

    Ejemplo: (Exponenciacin). Considrese el problema de calcular xn, n entero positivo.

    Pot1 (real x, entero positivo n)resultado = x;for i=1 to n 1 do

    resultado = resultado* xreturn resultado

    Si 1(n) es el nmero de multiplicaciones requeridas, evidentemente para calcular xn en

    funcin de n, ser 1(n)= n-1 nmero de multiplicaciones. Es decir 1(n)= (n).

    Ejemplo:(Bsqueda Exhaustiva). Buscar un producto especfico en el supermercado endonde no conocemos la distribucin de sus productos. Si el producto es un alimentocongelado, de inmediato nos dirijimos al pasillo o sector donde se encuentran los alimentos

  • 5/21/2018 Cap_9-10-11_2010

    2/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    2

    congelados, sin recorrer otro pasillo. Sin embargo, los algoritmos de Fuerza Bruta ignoranesta alternativa e ingenuamente buscan a travs de todas los pasillos en el intento de encontrarel objeto o producto deseado.

    Ejemplo: (Problema de la mxima suma). Dada una sucesin X de nmeros enteros. Sebusca la mxima suma que se puede generar, desde un conjunto de elementos. Por ejemplo,

    X[0] X[1] X[2] X[3] X[4] X[5] X[6] X[7] X[8] X[9]

    31 -41 59 26 -53 58 97 -93 -23 84

    La suma parcial X[2] + X[3] + X[4] + X[5] + X[6] con los valores (59 + 26 53 + 58 + 97) =187 soluciona el problema. Diversas otras soluciones existen sobre el particular.

    public static int maxSubsum1(int a[]){/* 1 */ int maxSuma = 0;/* 2 */ for (int i = 0; i < a.length;i++)/* 3 */ for (int j = i; j < a.length; j++)

    {/* 4 */ int suma = 0;/* 5 */ for (int k = i; k maxSuma)/* 8 */ maxSuma = suma;

    }/* 9 */ return maxSuma;}

    El anlisis de tiempo de ejecucin esta dado por )(11

    3= = =

    =N

    i

    N

    ij

    j

    ik

    NO .

    b) Dividir para Reinar(DpR)

    Digamos que un algoritmo recursivo es un algoritmo que contiene un procedimientorecursivo. La recursin es una forma poderosa, elegante y natural de resolver una ampliagama de problemas, aunque en general debemos decir que poseen una deficiencia en lostiempos de ejecucin. En general, problemas de esta naturaleza pueden resolverse medianteuna tcnica llamada Dividir para Reinar, en la cual el problema se descompone ensubproblemas del mismo tipo que el original, los que a su vez vuelven a particionarse ensubproblemas hasta que este proceso genera subproblemas que se pueden resolver de maneradirecta. Finalmente, las soluciones entregadas por los subproblemas se combinan para

    obtener una solucin del problema original. Cabe sealar que la tcnica Dividir para Reinarresuelve un problema de tamao n, descomponindolo en varios subproblemas que sonsimilares al problema original, excepto que son de tamao ms pequeo, sin considerar si lossubproblemas que se generan tras esta descomposicin son los ms ptimos. Es decir, lacondicin de "optimizacin" no es lo trascendente. Por otro lado, cada uno de estossubproblemas son resueltos de manera independiente y a continuacin los resultadosobtenidos de la resolucin de cada uno de estos subproblemas se combinan para generar lasolucin al problema original. La resolucin de un problema mediante esta tcnica constafundamentalmente de los siguientes pasos:1. En primer lugar ha de plantearse el problema de forma que pueda ser descompuesto en k

    subproblemas del mismo tipo, pero de menor tamao. Es decir, si el tamao de la entrada es n,

    hemos de conseguir dividir el problema en k subproblemas (donde 1 k n), cada uno conuna entrada de tamao nk y donde 0 nk < n. A esta tarea se le conoce como divisin.

  • 5/21/2018 Cap_9-10-11_2010

    3/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    3

    2. En segundo lugar han de resolverse independientemente todos los subproblemas, biendirectamente si son elementales o bien de forma recursiva. El hecho de que el tamao de lossubproblemas sea estrictamente menor que el tamao original del problema nos garantiza laconvergencia hacia los casos elementales, tambin denominados casos base.

    3. Por ltimo, combinar las soluciones obtenidas en el paso anterior para construir

    la solucin del problema original.As se visualiza una estructura general de la tcnica DpR en forma recursiva se ven as:

    Dado un problema P.If P es divisible en problemas ms pequeos then

    Divide P en 2 o ms partes: P1, P2, ....Pk. //Etapa DividirResuelve P1;Resuelve P2;......Resuelve Pk; // Etapa consolidacin para reinar

    Mezcla las k-sol. parciales en una solucin para P. //combinarelse

    Resuelve P directamente

    Cabe mencionar que, en general, la recursividad puede ser simulada con ayuda de iteraciones.Ahora, si bien es cierto que soluciones recursivas son fciles de entender y de implementar,sin embargo, la desventaja ms recurrente para su ejecucin es la necesidad de una grancantidad de espacio en memoria.

    La ventaja de los algoritmos de simplificacin es que consiguen reducir el tamao delproblema en cada paso, por lo que sus tiempos de ejecucin suelen ser muy buenos(normalmente de orden logartmico o lineal). Adems pueden admitir una mejora adicional,

    puesto que en ellos suele poder eliminarse fcilmente la recursin mediante el uso de un bucleiterativo, lo que conlleva menores tiempos de ejecucin y menor complejidad espacial al noutilizar la pila de recursin, aunque va en detrimento de la legibilidad del cdigo resultante.

    Respecto a la complejidad de este tipo de algoritmos sealemos que cuando un algoritmocontiene una llamada a s mismo, el tiempo de ejecucin puede ser descrito por una ecuacinde recurrencia. En general si T(n) es el tiempo de ejecucin de un problema de tamao n, y lo

    procedemos a particionar en a-subproblemas, cada uno de los cuales es de tamao 1/b delproblema original, entonces la recurrencia queda expresada por T(n) = aT(n/b) + D(n) + C(n),en donde D(n) es el tiempo utilizado para dividir el problema en subproblemas y C(n) eltiempo para combinar la solucin de los subproblemas en una solucin al problema original.

    Ejemplo (Algoritmos de ordenamiento). Bajo esta metodologa se pueden mencionar porejemplo, InsertionSort donde la particin del archivo de tamao n es escindido en 2subproblemas uno de tamao n-1 y otro de tamao 1, generando la recurrencia T(n)= T(n-1) +n. Otro algoritmo es QuickSort, o MergeSort

    QuickSort(Array A, int p, int r)int q;{ if (p < r)

    { q = Particion(A, p, r);QuickSort(A, p, q);QuickSort(A, q+1, r);

    }}

  • 5/21/2018 Cap_9-10-11_2010

    4/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    4

    Recordar que si la etapa de particion de QuickSort toma n -1 elementos y otra con un soloelemento, el tiempo de ejecucin es T(n) = T(n-1) + O(n). Dicho de otro modo si la etapa de

    particin n -1 comparaciones, entonces la recurrencia para expresar el nmero decomparaciones es C(n) = n -1 + C(a) + C(b), donde a y b son los tamaos de L1 y L2,generalmente satisfacen a+b = n -1. En el peor caso, x es el elemento mnimo en L. Entonces,a = 0 , b = n -1, y la recurrencia queda C(n)=n -1 + C(n -1) = O(n 2). As podr ver, que

    tambin existe un caso peor que lo deja en igualdad de condiciones con InsertionSort. Pero sila particin genera dos regiones de tamao n/2 QuickSort mejora en forma substancial, puesla recurrencia es T(n) = 2T(n/2) + O(n), cuya solucin es O(nlogn). Tambin existensituaciones en donde pueden balancearse, es decir recurrencias del tipo T(n) = T(9n/10) +T(n/10) + n, pero que no generan cambios substanciales respecto a la anterior.

    Otro algoritmo es en donde la particin del archivo de tamao n se escinde en dos partesiguales, llamado MergeSort

    MergeSort(Lista L){

    if (longitud(L) < 2) return Lelse {particiona L en listas L1 y L2, con n/2 elementosL1 = mergeSort(L1)L2 = mergeSort(L2)return merge(L1,L2)

    }}

    la que genera una recurrencia del tipo T(n)=T( piso(n/2) + T(techo(n/2)), cuya resolucin seinterpreta como la complejidad del algoritmo.

    Ejemplo: (Problema de la mxima suma). Retomamos el problema de la suma mxima,usando esta vez una estrategia DpR que representa una solucin algortmica general. Enefecto,Dividir: Particionar el problema de tamao N en (al menos) 2 subproblemas, cuando N > 1 ,sino solucionar directamente el problema de tamao 1.Reinar: Solucionar los subproblemas de la misma forma.Combinar: Combinar las soluciones parciales.

    a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7]

    4 -3 5 -2 -1 2 6 -21. Mitad 2. Mitad

    La suma ms grande en la primera mitad es 6 (a[0] + a[1] + a[2]), la suma ms grande en lasegunda mitad es 8 (a[5] + a[6]). La suma maximal en la 1. Mitad, en la cual es considerado elltimo elemento de la 1. Mitad inclusive, es decir (a[0] + a[1] + a[2] + a[3]) es 4. La sumamaximal en la 2. Mitad, en la cual se considera el primer elemento de la 2. Mitad es 7. Lasuma maximal que abarca ambas mitades es 4 + 7 = 11.

    private static int maxSucSum(int a[], int izq, int der)

    {/* 1 */ if (izq == der)/* 2 */ if (a[izq] > 0) // Caso que este elemento sea positivo

  • 5/21/2018 Cap_9-10-11_2010

    5/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    5

    /* 3 */ return a[izq]; // luego este es el max.Suma parcial/* 4 */ else return 0;/* 5 */ int mitad = (izq + der) / 2;/* 6 */ int maxIzqSuma = maxSucSum(a, izq, mitad);/* 7 */ int maxDerSuma = maxSucSum(a, mitad + 1, der);/* 8 */ int maxLimiteIzqSuma = 0, limiteIzqSuma = 0;

    /* 9 */ for (int i = mitad; i >= izq; i--){

    /*10 */ limiteIzqSuma += a[i];/*11 */ if (limiteIzqSuma > maxLimiteIzqSuma)/*12 */ maxLimiteIzqSuma = limiteIzqSuma;

    }/*13 */ int maxLimiteDerSuma = 0, limiteDerSuma = 0;/*14 */ for (int i = mitad + 1; i maxLimiteDerSuma)/*17 */ maxLimiteDerSuma = limiteDerSuma;

    }/*18 */ if (maxIzqSuma > maxDerSuma)

    if (maxIzqSuma > (maxLimiteDerSuma + maxLimiteIzqSuma))return maxIzqSuma;

    else return (maxLimiteDerSuma + maxLimiteIzqSuma);else if (maxDerSuma > (maxLimiteDerSuma +

    maxLimiteIzqSuma) )return maxDerSuma;

    else return (maxLimiteDerSuma + maxLimiteIzqSuma);}

    public static int maxSucSum3(int a[]){return maxSucSum(a, 0, a.length - 1);}

    La implementacin toma un tiempo O(NlogN).

    Ejemplo: (Bsqueda Binaria). Dado un nmero X y una sucesin de nmeros enteros A0,A1, A2, ... , AN-1 en memoria. Se pide hallar la posicin i tal que Ai=X , y por otro ladodevuelve i=-1 si X no fue encontrado.

    public static int Bbin(Comparable a[], Comparable x){/* 1 */ int izq = 0, der = a.length - 1;/* 2 */ while (izq < der)

    {/* 3 */ int mitad = (izq + der) / 2;/* 4 */ if (a[mitad].compareTo(x) < 0)/* 5 */ izq = mitad + 1;/* 6 */ else if (a[mitad].compareTo(x) > 0)/* 7 */ der = mitad - 1;

    else/* 8 */ return mitad; // hallado

    }/* 9 */ return -1; // No hallado}

    Podemos ver que la lnea 2 es decisiva en la bsqueda del elemento. Comienza con (der izq) = N-1 y termina con (der izq) = -1. Junto a cada pasada por el ciclo se debe particionar

    en mitad(der izq). Si (der izq) = 128, luego los valores maximales segn cada iteracin es:64, 32, 16, 8, 4, 2, 1, 0, -1. El tiempo de ejecucun es O(logN), como se puede ver tras laresolucin de la ecuacin de recurrencia

  • 5/21/2018 Cap_9-10-11_2010

    6/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    6

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

    # subproblemas tamao del subproblema dividir & combinar

    La bsqueda Binaria es la implementacin de un Algoritmo para una estructura de datos (dealmacenamiento secuencial Lista, Array). Para la bsqueda de algn elemento necesita detiempo O(logN). Toda otra operacin (p.e. Agregar) necesita tiempo O(N).

    Ejemplo: Podemos plantearnos tambin disear un algoritmo de bsqueda ternaria, queprimero compara con el elemento en posicin n/3 del vector, si ste es menor que el elementox a buscar entonces compara con el elemento en posicin 2n/3, y si no coincide con xbuscarecursivamente en el correspondiente subvector de tamao 1/3 del original. Conseguimos asun algoritmo mejor que el de bsqueda binaria?.

    Ejemplo: (Exponenciacin). Retomando el problema, pero con un enfoque recursivo

    alternativo a Pot1(), en tal caso se piensa si xnpuede ser calculado obteniendo el cuadrado de n/2x y a continuacin multiplicando el resultado por x si n es impar. Es decir: xn = n/2n/2 xx . x , si n impar, xn= n/2n/2 xx , si n par. Si en particular se usa Pot1() para

    calcular n/2x se tendrn n/2 multiplicaciones. Luego para completar el clculo de xn, se

    requiere o bien una, o bien dos multiplicaciones adicionales dependiendo si n es par o impar.

    De este modo, simplemente calculando n/2 y usando este resultado para calcular xn,tenemos un medio efectivo para reducir aproximadamente a la mitad el nmero demultiplicaciones requeridas para calcular xn. Sin embargo, utilizando esta misma alternativa

    podra ser posible de calcular n/2x . En concreto, Pot1() puede usarse para calcular x

    2

    n/2 ,

    y este resultado se eleva al cuadrado (y se multiplica por x si n/2 es impar) para formar xn/2,

    y as sucesivamente generando el algoritmo.

    Pot2 ( real x, entero positivo n)if n = 1 then

    return x

    y = Pot2 (x,n/2)if n es impar then

    return y y xelse

    return y y

    Sabemos que en el mejor caso, cuando n = 2k , Pot2( ) realiza kmultiplicaciones, dedonde k = log2(n). En general, (log n) - nmero de multiplicaciones.

    Ejemplo.(multiplicacin de enteros grandes).Considerar el producto de dos enteros X e Yde n-bits. Recordar que el algoritmo que Ud. conoce de la escuela, bien podra considerarse defuerza bruta, dado que el costo es O(n2), si se toman las multiplicaciones y las adiciones de unsolo bit o dgito como un paso. Una estrategia DpR considera dividir X e Y en dos enteros den/2 bits cada uno.X = B + A2n/2Y = D + C2n/2

    A lo que el producto XY puede escribirse como XY = BD + AC2

    n

    + (AD + BC)2

    n/2

  • 5/21/2018 Cap_9-10-11_2010

    7/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    7

    Realizando 4-multiplicaciones de enteros de n/2 - bits (AC, AD, BC, BD), 3-sumas de enteroscon un mximo de 2n-bits. Generando una recurrencia

    T(1) = 1.T(n) = 4T(n/2) + cn,

    cuya resolucin es del orden O(n2

    ) no mejor a la que aprendi en la escuela. Sin embargo siahora se hacen los cambios

    XY = BD + AC2n+ [(A - B)(D - C) + AC + BD]2n/2

    Aunque parezca ms complicado, slo requiere 3-multiplicaciones de enteros con n/2-bits,AC, BD y (A - B)(D - C), generando la recurrencia T(1) = 1. T(n) = 3T(n/2) + cn, cuyasolucin es aproximadamente O(n1.5849625), mejorando substancialmente la performance de loaprendido en la escuela.

    Por ejemplo, con

    X= 31785=124* 256 + 41, donde a=124, b=41Y= 29846=116*256 + 150, donde c=116, d=150.Obteniendo el siguiente producto ac= 14384, bd= 6150, (a + b)(c + d) ac bd = 23356.

    Ejemplo(Multiplicacin de Matrices).Multiplicar A por B genera una matriz C todas ellasde orden n x n. De donde el tiempo para computar C es del orden n3. En donde n2 son loscoeficientes cij de C y n para calcular todos los cij. Este es el algoritmo bsico que Ud.conoce. Sin embargo la matriz anterior se puede pensar como una matriz n x n = 2 x 2matrices de n/2 x n/2 submatrices a saber C = A x B, es decir

    r s a b e g= x

    t u c d f h

    con esto podemos decir que

    r = ae + bf, s = ag + bh, t = ce + df, u = cg + dh

    de donde una multiplicacin en una matriz n x n es "reducida" a 4-ecuaciones, de las cuales senecesitan 2-multiplicaciones de dos n/2 x n/2 matrices, 1- suma de dos n/2 x n/2 matrices,

    dando en total 8-Multiplicaciones y 4- adiciones.

    T(n) = 8 T( n/2) + ( n2 )

    # subproblemas tamao del subproblema dividir & combinar

    no logrndose una mejora, pues la solucin es de orden n3. Sin embargo, Strassen propuso laidea de multiplicar 2 x 2 matrices con solamente 7- multiplicaciones( en vez de 8), lo hizoconsiderando

    P1 = a ( g - h )

    P2 = ( a + b ) hP3 = ( c + d ) eP4 = d ( f - e )

  • 5/21/2018 Cap_9-10-11_2010

    8/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    8

    P5 = ( a + d ) ( e + h)P6 = ( b - d ) ( f + h)P7 = ( a - c ) ( e + g), en donder = P5 + P4 - P2 + P6s = P1 + P2t = P3 + P4

    u = P5 + P1 - P3 - P7.

    Segn este principio se necesitan 7-multiplicaciones y 18 adiciones o restas.

    T(n) = 7 T( n/2) + ( n2 )

    # multiplicaciones tamao del subproblema dividir & combinar

    cuya solucin es ( n2.81).(teo. Maestro), de manera que (n2.81) v/s ( n3) gana para n>=50 enla practica.

    c) Programacin Dinmica

    Un algoritmo de programacin dinmica almacena los resultados, o soluciones desubproblemas ms pequeos y posteriormente los consulta en lugar de volver a calcularlos,

    para cuando los necesita para resolver subproblemas ms grandes. De manera que PD esidnea para problemas en los que un algoritmo recursivoresolvera muchos de lossubproblemas varias veces. En general la idea es convertir una solucin recursiva en unalgoritmo de programacin dinmica. La esencia de los algoritmos de programacin dinmicaes que cambian espacio por rapidez almacenando soluciones a subproblemas en lugar devolver a resolverlos. En general, laprogramacion dinamica debe su nombre al siguiente tipo

    de problema. Unprocesoes examinado al principio de cada uno de N periodos sucesivos. Delexamen resulta un valor x que es una (o ms) variable que sirve para juzgar la situacion delproceso. Sea (k,x) el dato correspondiente al periodo k. En base a esta informacion elegimos

    una accioncorrectivad tomada de un conjunto D(k,x). Esto provoca una transicion a (k+1,x) donde x = T(k,x,d) con un costo de la trancisin c(k,x,d). Se plantea el problema dedeterminar las acciones correctivas en cada una de los N periodos de forma que la suma de loscostos de los N periodos sea mnimo.

    Algunas observaciones que debe tener en cuenta son:

    Atacar el problema de arriba hacia abajo como si fuera a desarrollar un algoritmorecursivo; determinamos cmo resolver un problema grande suponiendo que conocemos

    soluciones para problemas ms pequeos. Guardando los resultados de los problemas pequeos podremos evitar clculos repetidos. Decidir que estructura de dato es la ms apropiada, en muchos casos lo mejor es un array

    uni o bidimensional.

    Determinar finalmente como obtener la solucin del problema a partir de los datos

    Los coeficientes binomiales se prestan en forma ideal para aplicar lo antes visto. Sabemos quelos coeficientes binomiales se pueden definir con la ecuacin de recurrencia

    C(n, k)= C(n -1, k -1) + C(n 1, k) , para n >0 y k >0.C(n, 0)= 1, si n 0.C(0, k) = 0, si k >0.

  • 5/21/2018 Cap_9-10-11_2010

    9/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    9

    En donde, C(n, k) tambin se puede interpretar como el nmero de formas en que podemosescoger k objetos distintos de un conjunto de n objetos. En este primer programa se muestra lafuncin sugerida por la relacin de recurrencia dada para C(n,k).

    /*Calculo de Binomio(m, n) usando una metodologa dividir para Reinar.*/

    public class BinomialDpR {

    static int[][] llamadas;

    static int Binom(int m, int n) {if (n == 0)return 1;

    else if (m == 0)return 0;

    elsereturn Binom(m-1, n) + Binom(m-1, n-1);

    }

    public static void main (String[] args) {llamadas = new int[31][16];

    System.out.println(Binom(30, 15));System.out.println(llamadas[0][7]);for (int i = 0; i

  • 5/21/2018 Cap_9-10-11_2010

    10/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    10

    public static void main (String[] args) {System.out.println(escoger(30, 15));

    }}

    Ud. podr ver a simple vista la rapidez de este ltimo al compararlo con el primero.

    Otro ejemplo clasico es el problema del orden de multiplicacin de matrices, que es uno delos ejemplos clsicos dentro de la Programacin dinmica. El propsito no es tan solo mostrarla forma de resolver el problema del orden de la multiplicacin de matrices, sino ms biencomo aplicar los principios de desarrollo de un algoritmo de Programacin Dinmica.

    Comencemos por definir una Matriz A de orden n m, la que est compuesta por elementos ai, j , dispuestos en un arreglo, con n-filas y m-columnas

    a 1, 1 a 1, 2 ....... a 1, m

    a 2, 1 a 2, 2 ....... a 2, m

    A = a 3, 1 a 3, 2 ....... a 3, m...

    . ..

    a n,1 a n,2 ......... a n,m

    Dada una matriz A de orden p q , y una matriz B de orden q r. La multiplicacin A B es

    una matriz C de orden p r, dada por c i, j = q a i, kb k,jk=0

    para 1 i p, y 1 j r.

    Observaciones.

    Si AB esta definida puede que BA no este definida, puede ocurrir que AB BA,Recursivamente definimos el productoA1A2A3A4A5..... As-1Ascomo A1(A2(A3(A4(A5..... (As-1As))).La multiplicacin de matrices es asociativa, es decir,

    A1A2A3= (A1A2)A3= A1(A2A3).

    La complejidad de la multiplicacin de matrices es del orden O(pqr). Notar que C tiene pr entradas y toda entrada toma tiempo O(q).

    Dada A de orden p q , B de orden q r, y una matriz C de orden r s, entonces D puede sercalculada en dos sentidos, A(BC), o (AB)C. Entonces el nmero de multiplicacionesnecesarias es :

    Mult [(AB)C] = p q r + p r s,Mult [A(BC)] = q r s + p q s, si ahora p= 5, q=4, r= 6 y s=2, entoncesMult [(AB)C] = 180,Mult [A(BC)] = 88, muestran , segn sea el caso una gran diferencia.

    Por lo tanto la sucesin de multiplicaciones es de suma importancia.

  • 5/21/2018 Cap_9-10-11_2010

    11/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    11

    Problema: Dada una sucesin de matrices A1, A2, A3, A4.. An y dimensiones p0, p1, p2,

    p3,...., pn, en donde Aies de dimensin pi-1pi, donde 1 i n. Determinar la sucesin demultiplicaciones que minimiza el nmero de multiplicaciones. Es decir, en otras palabras,

    Cmo deberemos calcular A1A2A3A4..An y cul es el costo mnimo de hacerlo?.

    Notar que si se tienen matrices M= A1A2A3A4de orden 10 20, 20 50, 50 1, 1 100, evaluando M en el orden A1(A2(A3A4)) requiere 125.000 operaciones, mientrasque (A1 (A2 A3)) A4 requiere solamente 2.200 operaciones, de manera que laoptimizacin de la sucesin de parentizacin es de suma importancia y bien vale considerarla.

    Sea T(n) las formas distintas de parentizar n-matrices, en el caso para M se tena T(4)=5, endonde se mostraron dos de las 5-posibilidades.En general se tiene

    n -2

    T(n) = T(i) T(n i), para n > 1.i=1

    En efecto, sean las matrices A1 , A2 , A3 , A4 .. An y la ltima multiplicacin realizada es

    T(i)= (A1A2A3A4.. Ai ) (Ai+1Ai+2Ai+3.. An ) = T(n-i) , de manera que existen T(i) T(n i) formas de calcular el producto para cada i posible. La solucin de esta recurrencia esta dada

    por T(n-1) = 1/(n-1)Comb(2n, n), que es el nmero de Catalan cuyo resultado es de ordenexponencial.

    Desarrollando una propuesta en Programacin Dinmica.

    Etapa 1: Determinar la estructura de una solucin optimal, (en este caso una parentizacinoptimal).

    Descomponer el problema en subproblemas: Para cada par 1 i j n, determinar lasucesin de multiplicaciones para A i...j = A iAi+1 .. Aj que minimiza el nmero de

    multiplicaciones. Claramente Ai...j =AiAi+1 .. Aj es una matriz pi-1 pj, Problema Original:Determinar la sucesin de multiplicaciones para A1....n.

    Parentizacin de alto nivel para Ai...j, para cualquier sucesin de multiplicaciones optimal seencontrara que en la ltima etapa se debe realizar el producto de dos matrices Ai...k yAk+1...j, para algn k esto es:Ai .. j = (AiAi+1.. Ak ) (Ak+1.. Aj ) = (Ai .. k ) (Ak+1.. j )

    esto se interpreta en forma particular como

    A3 .. 6= (A3 (A4 A5 )) (A6 ) = (A3 .. 5 ) (A6.. 6 ), donde k=5

    entonces el problema de determinar la sucesin de multiplicaciones optimal es cuestionada entrminos a considerarCmo decido donde particionar la cadena o sucesin, es decir quin es k?.(debemos buscar entre todos los posibles....valores de k.)Cmo parentizar las subcadenas (Ai .. k ) (Ak+1.. j )?(debemos aplicar el mismo procedimiento en forma recursiva).

    Principio de Optimizacin

  • 5/21/2018 Cap_9-10-11_2010

    12/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    12

    Notar que este problema satisface el principio de Optimizacin, pues si queremos encontrar lasucesin de multiplicaciones optimal Ai .. j debemos usar la sucesin optimal para (A i .. k ) y

    para (A k+1.. j ), en otras palabras los subproblemas deben ser resueltos en forma optimal paraque el problema global sea resuelto en forma optimal.

    Etapa2: Recursivamente definimos el valor de una solucin optimal.

    En este sentido, almacenamos las soluciones de los subproblemas en una tabla, en donde paracada par 1 i j n, m[i, j] denota el nmero mnimo de multiplicaciones necesarias paracomputar Ai .. j. El costo optimal puede ser expresado por la siguiente definicin recursiva.Recursivamente definimos el valor de una solucin optimal, en donde

    m[i, j] = 0, si i=j m[i, j] = Minimo 1 k

  • 5/21/2018 Cap_9-10-11_2010

    13/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    13

    Fig. 1 Fig. 2

    En Fig. 2, computamos m[1, 2], que por definicin est dado por:

    m[1, 2] = Mnimo 1 k

  • 5/21/2018 Cap_9-10-11_2010

    14/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    14

    m[1, 3] = Mnimo 1 k

  • 5/21/2018 Cap_9-10-11_2010

    15/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    15

    La idea es mantener un array s[1.. n, 1.. n], donde s[ i, j ] denota k para la particin optima enlos clculos de Ai .. j = Ai .. k Ak+1.. j .El array s[1.. n, 1.. n], puede ser usado recursivamente para recubrir la sucesin demultiplicaciones.Cmo recubrir la sucesin de multiplicaciones.?s[1, n] corresponde (A1 .. As[1,n] ) (As[1,n]+1 .. An )

    s[1, s[1, n]] corresponde (A1 .. As[1, s[1,n]] ) (As[1, s[1,n]] +1 .. As[1,n] )s[s[1, n] + 1, n]..... y as sucesivamente.

    Se construye una solucin optimal a partir de la informacin calculada. El cdigo actual demultiplicacin usa el valor s[i, j] para determinar como particionar o escindir la sucesinactual. Asumamos que las matrices son almacenadas en un array de matrices A[1..n], y ques[i, j] es global para este procedimiento recursivo. El siguiente procedimiento recursivoentrega la cadena de un producto matricial A i .. j dada por las matrices A1, A2, A3, A4.. An,la tabla s computada por Cadena_Matriz(p, n) y los indices i, j. La llamada inicial a este

    procedimiento se hace a travs de Mult(A, s, 1, n).

    Mult(A, s, i, j)if j > i

    then X= Mult(A, s, i, s[i, j] ) // X = A i .. k donde k = s[i, j]Y= Mult(A, s, s[i, j] + 1, j) // Y = A k+1 .. jreturn Mult_Matrices_Usual(X, Y)

    else return Ai

    Veamos ahora cmo encontrar la sucesin de multiplicaciones optimal.Supongamos que las tablas m y s ya fueron computadas por el procedimiento

    Cadena_Matriz(p, n) para n = 6 y las siguientes dimensiones. A1 de dimensin 30 35, A2 dedimensin 35 15, A3 de dimensin 15 5, A4 de dimensin 5 10, A5 de dimensin 10 20y A6 de dimensin 20 25. Tal como se muestra en Fig. 8.

    Fig. 8

    Consideremos n=6, y computemos A 1 .. 6 , asumiendo que el array computado es s[1..6,1..6]y de donde la sucesin de multiplicaciones corresponden aMult(A, s, 1, 6 ) s[1, 6] = 3 y que corresponde a (A1 A2 A3 ) (A4 A5 A6 )Mult(A, s, 1, 3 ) s[1, 3] = 1 (A1 (A2 A3 ))Mult(A, s, 4, 6 ) s[4, 6] = 5 ((A4 A5 )A6 )Mult(A, s, 2, 3 ) s[2, 3] = 2 (A2 )(A3)

    Mult(A, s, 4, 5 ) s[4, 5] = 4 (A4 ) (A5)de aqu entonces que la sucesin de multiplicaciones final es (A1 ((A2 ) (A3 ))) (((A4 ) (A5))A6 )

  • 5/21/2018 Cap_9-10-11_2010

    16/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    16

    Otra forma de representarlo es a travs de un Arbol de expresin aritmtica, tal como sevisualiza a continuacin, en donde cada nodo se identifica con un subproblema y representauna matriz o bien una multiplicacin a efectuar. Cada invocacin de Mult(A, s, i, j), visita unnuevo nodo del rbol de expresin, que posee 2n 1 nodos, as que existen 2n 1

    invocaciones, y Mult(A, s, i, j), tarda un tiempo (n).

    (1,6)*

    (1,3) (4,6)* *

    (2,3) (4,5)A1 * * A6

    A2 A3 A4 A5

    Ejemplo

    Matriz dimension r prA1 10*20 0 10A2 20*3 1 20A3 3*5 2 3A4 5*30 3 5

    4 301 2 3 4

    1 0 600 750 19502 0 300 22503 0 4504 0

    Construccin de la solucin optimal desde la informacin computada

    Ejemplo

    Matriz dimension r pr

    A1 10*20 0 10A2 20*3 1 20A3 3*5 2 3A4 5*30 3 5

    4 30

    1 2 3 41 A1 A1A2 (A1A2)A3 (A1A2)(A3A4)2 A2 A2A3 A2(A3A4)3 A3 A3A4

    4 A4

  • 5/21/2018 Cap_9-10-11_2010

    17/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    17

    ImplementacinArchivo MultMatPD.java/*Esta es una solucin programacin dinmica para determinarel orden optimal de una sucesin de matrices.Los argumentos en la lnea de comando son p0, p1, p2,..., pn, donde las

    matrices que deseamos multiplicar y tienen dimensiones (p0 x p1), (p1 xp2),..., (p(n-1) x pn) y en este orden.

    Ejemplo de uso:>java MultMatPD 30 35 15 5 10 20 25

    A1 (30 * 35)A2 (35 * 15)A3 (15 * 5)A4 (5 * 10)A5 (10 * 20)A6 (20 * 25)Izq_a_Der costo:40.500Producto Minimo costo: 15.125Parentizacin Optimal: ( (A1 )( (A 2 )(A3 )))(((A4 )(A 5 ))(A6))*/

    public class MultMatPD {

    public static void main(String args[]) {

    int n; // numero de matricesint[] dim; // n-sima matriz (n>0)tiene dim[n-1] filas y dim[n] columnasint[][] opt_cost; // opt_cost[i,j] es el costo optimal de multiplicar

    // la i-sima con la j-sima matriz (inclusive)int[][] partic; // partic[i,j] = k cuando la multiplicacin final en un//producto optimal de Ai...Aj es (Ai...Ak)(A(k+1)...Aj)

    int length, partida_pos, fin_pos, cost, actual_min, izqder_costo, i;

    // crear arrays y leer las dimensiones de las matricesn = args.length - 1;dim = new int[n+1];opt_cost = new int[n+1][n+1];partic = new int[n+1][n+1];

    //ingreso por tecladofor (i = 0; i

  • 5/21/2018 Cap_9-10-11_2010

    18/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    18

    if (actual_min == 0 || cost < actual_min) {

    // ya que el costo es siempre estrictamente positivo, sabemos// que si opt_cost[i,j]==0, no ha sido asignado por ahora.// Asi, testeamos para cero en vez de necesitar un valor// de "infinito".

    opt_cost[partida_pos][fin_pos] = cost;partic[partida_pos][fin_pos] = i;

    }}

    }}

    // print la lista de las matrices y sus dimensionesfor (i= 1; i

  • 5/21/2018 Cap_9-10-11_2010

    19/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    19

    String Matching (bsqueda en texto)

    Otro ejemplo de aplicacin de la Programacin Dinmica es String Matching. El problemastring matching se formaliza como sigue. Consideremos que un texto es un array T[1..n] delongitud n y que los pattern o formas es un array P[1..m] de longitud m. Se supone que loselementos de P y T son caracteres extrados de un alfabeto finito. El array de caracteres de P yT son a menudos llamados string de caracteres. Algoritmos String Matching sonfrecuentemente utilizados para la bsqueda de formas particulares en las sucesiones de ADN.

    Ejemplo: El objetivo es encontrar todas las ocurrencias del pattern P = abaa en el texto T =abcabaabcabac. Tal como se ve en Fig. 1 el pattern ocurre solamente una vez en el texto. Eneste caso todo carcter del pattern esta conectado por una lnea vertical y ensombrecido paracaracterizar los efectos del matching.

  • 5/21/2018 Cap_9-10-11_2010

    20/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    20

    Una implementacin naive es la que se propone, pero muy simple de implementar, la cualse basa en encontrar todos los shifts vlidos usando un loop que va chequeando lascondiciones P[1 ..m] = T[s+1..s+m] para toda de las n m + 1 posibles valores de s.

    Naive-String-Matcher(T, P)n=long[T];m= long[P]for s=0 to n-m doif P[1..m] = T[s+1..s+m] thenprint pattern ocurri en la posicin s.

    Implementacin del algoritmo y ejecucin del ejemplo, considerando que el texto T=abcabaabcabac y el pattern P= abaa, entregando como resultado posicin=3

    public class KMP_Naive {static int n = 1;

    private static int[] iniSig (String pattern) {int[] siguiente = new int [pattern.length ()];int i = 0, j = -1;siguiente[0] = -1;while (i < pattern.length () - 1) {while (j >= 0 && pattern.charAt (i) != pattern.charAt (j))j = siguiente[j];i++; j++;siguiente[i] = j;

    }return siguiente;

    }

    public static int kmp_Busca(String texto, String pattern) {int[] siguiente = iniSig (pattern);int i = 0, j = 0;n = 1;while (i < texto.length ()) {while (j >= 0 && pattern.charAt (j) != texto.charAt (i)) {j = siguiente[j];}i++; j++;if (j == pattern.length ())return i - pattern.length ();

    }return -1;

    }

    public static void main (String[] args) {String p = "abaa";//pattern Pint[] siguiente = iniSig(p);for (int i = 0; i < siguiente.length; i++)

    System.out.println ("siguiente[" + i + "] = " + siguiente[i]);System.out.println ("posicion = " + kmp_Busca("abcabaabcabac", p));}

    }

    Ahora si el pattern P es relativamente grande y el alfabeto de donde se extraen los caractereses razonablemente grande entonces el algoritmo de Boyer-Moore es ms eficiente para stringmatching.

  • 5/21/2018 Cap_9-10-11_2010

    21/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    21

    Dentro de este contexto se encuentran una serie de problemas, entre ellos el hallar lasubsecuencia comn ms larga entre 2 string, conocido como Longest CommonSubsequence, en adelante (LCS). Este es otro ejemplo clsico de la tcnica de programacindinmica. Antes de que definamos el problema general de la subsecuencia comn ms largo,empezamos con un pequeo ejemplo. Suponga que se da un string (como modelo) y un stringms largo (como texto). La idea es saber si los caracteres del modelo aparecen en orden (pero

    posiblemente separado) dentro del texto. Si ello ocurre, decimos que el modelo es unasubsecuencia del texto, y si es la subsecuencia ms grande por ejemplo "nomi" es unasubsecuencia de "conocimiento" como solucin al problema.

    Formalmente, digamos que una sucesin X = < x1, x2, ....., xm> y otra sucesin Z =< z1, z2, ....., zk> es una subsucesin de X si existe una sucesin de ndices estrictamente creciente i1, i2, ....., ikde ndices de k, tal que para todo j=1, 2, 3..., k, se tiene x i j= z j. Por ejemplo,Z= es una subsucesin de X= , con subndices . Dadas dos secuencias X e Y, se dice que una sucesin Z es una subsucesin comn de X eY si Z es una subsucesin de ambas , es decir de X e Y. Por ejemplo, si X= , Y= < B, D, C, A, B, A> entonces la sucesin es una subsucesin comn

    de X e Y. Observar que no es la ms larga de X e Y, pues es tambincomn a ambas y tiene longitud 4. Notar que tampoco es nica, pues la sucesin tambin lo es. Sin embargo, no existe LCS de longitud 5 o mayor.

    Por qu podramos querer nosotros resolver el problema de la subsecuencia comn mslarga?Hay varias aplicaciones que motivan este estudio.

    * En la biologa molecular. Sucesiones de ADN (genes) pueden representarse comosucesiones de cuatro elementos bsicos ACGT que se corresponden a las cuatro submoleculasque forman el ADN. Cuando los bilogos encuentran una nueva sucesin, ellos quieren saberqu otras sucesiones son similares a ella. De all que la computacin de las dos sucesionessimilares pasan por encontrar la longitud de su subsecuencia comn ms largo.

    * Comparacin de archivos. En Unix-Linux comandos "diff" se usan para comparar dosversiones diferentes del mismo archivo, para determinar qu cambios se han hecho al archivo.Funciona encontrando una subsecuencia comn ms larga de las lneas de los dos archivos; endonde cualquier lnea en la subsecuencia no se ha cambiado. En este caso debemos pensar quecada lnea de un archivo es un carcter dentro de un string.

    Un approach fuerza bruta para resolver LCS es enumerar todas las subsecuencias de X y

    chequearlas todas ellas para ver si es tambin subsecuencia de Y, hasta encontrar lasubsecuencia ms larga. Estas observaciones nos dan un algoritmo recursivo altamenteineficiente, pues recordar que toda subsecuencia de X corresponde a un subconjunto de losndices {1, 2, 3,..., m} de X, existiendo 2m subsucesiones de X, de manera que el tiempo esexponencial, hacindolo impracticable para sucesiones ms largas.

    Basado en Teorema 16.1 pg. 315 (CLR) podemos admitir una subestructura optimal de unLCS, y en este contexto al igual que en el problema de Parentizacin de Matrices se estableceuna recurrencia para el costo de una solucin optimal. Se define c[i,j] como la longitud de unLCS de secuencias Xi, Yj. Si i=0 o j=0 una de las sucesiones tiene longitud 0, as LCS tienelongitud 0. La subestructura optimal de LCS est dada por la formula recursiva:

  • 5/21/2018 Cap_9-10-11_2010

    22/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    22

    >

    =>+

    ==

    =

    ii

    ii

    yxyjijicjicmax

    yxyjijic

    joi

    jic

    0,]),1[],1,[(

    0,1]1,1[

    000

    ],[

    Basada en estas ecuaciones podramos escribir un procedimiento recursivo para computar lalongitud de un LCS de 2 secuencia, pues existen solamente O(mn problemas distintos.

    int lcs_long(char * A, char * B){if (*A == ' \0 ' || *B == ' \0 ') return 0;else if (*A == *B) return 1 + lcs_long(A+1, B+1);else return max(lcs_long(A+1,B), lcs_long(A,B+1));

    }

    Sin embargo, el objetivo es usar Programacin Dinmica. El procedimiento considera 2sucesiones X = < x1 , x2 , ....., xm> e Y =< y1 , y2 , ....., yn> como entrada, se procede aalmacenar los valores c[i,j], en una tabla c[0..m, 0..n] cuyas entradas son computadas primerafila de c es llenada de izq. a der., luego la segunda fila, y as sucesivamente. Al mismo tiempose mantiene una tabla

    b[1..m, 1..n] para simplificar la construccin de una solucin optimal.

    LCS-Long(X, Y)m= long[X]

    n= long[Y]for i=1 to m

    do c[i,0]=0for j=1 to n

    do c[0, j]=0for i=1 to m

    do for j=1 to ndo if xi= yj

    then c[i, j]= c[i -1,j -1] + 1b[i, j] =

    if else c[i -1, j ] c[i , j -1 ]then c[i, j]= c[i -1,j ]

    b[i, j] = else c[i, j]= c[i,j - 1]

    b[i, j] = return c y b.

    La fig. 2 muestra la tabla que se genera por el procedimiento anterior sobre la secuencia X= e Y= < B, D, C, A, B, A>. El tiempo de ejecucin del procedimiento esclaramente O(mn).

  • 5/21/2018 Cap_9-10-11_2010

    23/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    23

    El siguiente procedimiento recursivo imprime la salida de LCS de X e Y. La llamada iniciales printLCS(b, X, long[X], long[Y]).

    printLCS(b, X, i, j).if i=0 o j=0then return

    if b[i, j] =

    then printLCS(b, X, i -1, j -1) print xielse if b[i, j] =

    then printLCS(b, X, i -1, j )else printLCS(b, X, i , j 1 )

    Para la tabla b en Fig. 2 este procedimiento imprimeBCBA.

    Implementacin

    /*Hallar la Longest Common Subsequence, LCS de 2 secuencias como entrada,

    usando Programacin Dinmica. Considerar que el programa lee losargumentos de la lnea de comando.El primer argumento es la cadena X de caracteres o string, en este caso se

    consideran solo enteros(int)mientras que el segundo argumento es la cadena Y de caracteres o string,

    tambin enteros(int).la linea de comando es: x1 x2 ... xm . y1 y2 ... ynPara notar el termino de una cadena con respecto al inicio de la otrase considera un punto "." como separador.Ejemplo de uso

    >java LCS 1 0 0 1 0 1 0 1 . 0 1 0 1 1 0 1 1 0

    1 0 0 1 0 1 0 10 1 0 1 1 0 1 1 0LCS tiene longitud: 6

    1 0 0 1 1 0*/

    public class LCS {

    public static void main(String[] args) {

    int[] x, y; // las 2 secuenciaint n, m; // x's van de x1 a xn; y's van de y1 a ym

    int[][] longit; // longit[i][j] es la longitud de la subsucesion//comun mas grande de la long-i subsucesion de los x's, y la long-j//subsucesion de los y's.

    int[][] reconstruir;//es la variable "b" ,//util para simplificar la construccion de una solucion optimal.

    int i, j, k, xs, ys;

    // lee la linea de comando con los argumentosk = args.length;i=0;while (! args[i].equals("."))

    i++;

    n = i;m = k - i-1;x = new int[n+1]; // parten los indices en 1y = new int[m+1];

  • 5/21/2018 Cap_9-10-11_2010

    24/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    24

    for (j=0; j

  • 5/21/2018 Cap_9-10-11_2010

    25/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    25

    printLCS(reconstruir, x, n-1, m-1);System.out.print(" " + x[n]);

    }else if (reconstruir[n][m] == 2)

    printLCS(reconstruir, x, n, m-1);else

    printLCS(reconstruir, x, n-1, m);}

    }

    Aqui aparece con un MVC asociado.

    Bajo un esquema similar es posible presentar la siguiente aplicacin: Dada una sucesin deenteros X = < x1 , x2, ....., xm>, los cuales no contienen elementos duplicados, entonces es

    posible disear un algoritmo para encontrar la subsucesin creciente ms grande xi1

  • 5/21/2018 Cap_9-10-11_2010

    26/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    26

    3 5 6 8 9 12 23 4^ ^ ^ ^ ^ ^ ^Una LIS tiene longitud 7.

    */public class LIS {

    public static void main(String[] args) {

    int n; // la longitud de la suc de entradaint[] x; // la sucesion de entradaint[] lis; // lis[i] es la longitud de la LIS(longest increasing

    //subsequence), cuyo miembro final es x[i].int[] previo; /* si x[i] pertenece a una LIS determinada por el

    algoritmo, previo[i] es el indice de los predecesor x[i]'s enla LIS. El miembro inicial de la LIS tiene previo[i] = n. */

    boolean[] en_LIS; // en_LIS[i] es true ssi x[i] esta en la LIS.

    int i, j, k, lis_valor, lis_max, k_max, i_max, fin_de_longest;

    // inicializar variables y leer la sucesin de entrada, desde la lnea //decomando.

    n = args.length;x = new int[n];lis = new int[n];previo = new int[n];en_LIS = new boolean[n];for (i=0; i < n; i++)

    x[i] = Integer.parseInt(args[i]);

    // hallar una LIS, sin contar la existencia del total de ellas.

    lis[0] = 1;previo[0] = n;

    i_max = 0;fin_de_longest = 0;

    for (i=1; i lis_max) {

    lis_max = lis_valor;k_max = k;

    }}

    lis[i] = lis_max + 1;if (lis_max == 0)previo[i] = n;

    elseprevio[i] = k_max;

    if (lis[i] > i_max) {i_max = lis[i];fin_de_longest = i;

    }}

    //marca todos los elementos que estan en la LIS

    j = fin_de_longest;en_LIS[j] = true;while (previo[j] != n) {

  • 5/21/2018 Cap_9-10-11_2010

    27/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    27

    j = previo[j];en_LIS[j] = true;

    }

    //print la sucesin de entradaSystem.out.println();for (i=0; i

  • 5/21/2018 Cap_9-10-11_2010

    28/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    28

    Ejemplo

    Dada la siguiente tabla de palabras junto con sus frecuencias de acceso, se muestran algunosde los clculos correspondientes a los valores que sern almacenados en las matrices de costosC[i,j] y de races R[i,j].

    i K i P i

    1 A 20

    2 Bien 10

    3 Con 30

    4 De 15

    5 El 25

    C( 1,2 ) = min { ( C(1,0) + C(2,2) + P1+ P2 ), C(1,1) +C(3,2) +P1 +P2 }i =1 i =2

    C(1,2 ) = min { 40 , 50 } = > C(1,2) = 40 ; R(1,2) =1

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 1 1 1

    2 0 10 2 0 2

    3 0 0 30 3 0 0 3

    4 0 0 0 15 4 0 0 0 4

    5 0 0 0 0 25 5 0 0 0 0 5

    C( 2,3 ) = min { ( C(2,1) + C(3,3) + P2+ P3 ), C(2,2) +C(4,3) +P2 +P3 }i =2 i =3

    C(2,3 ) = min { 70 , 50 } = > C(2,3) = 50 ; R(2,3) =3

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 1 1 1

    2 0 10 50 2 0 2 3

    3 0 0 30 3 0 0 3

    4 0 0 0 15 4 0 0 0 4

    5 0 0 0 0 25 5 0 0 0 0 5

    C( 3,4 ) = min { ( C(3,1) + C(3,3) + P3+ P4 ), C(3,2) +C(4,3) +P3 +P4}i =3 i =4

    C(3,4 ) = min { 60 , 75 } = > C(3,4) = 60 ; R(3,4) =3

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 1 1 1

    2 0 10 50 2 0 2 3

    3 0 0 30 60 3 0 0 3 3

    4 0 0 0 15 4 0 0 0 4

    5 0 0 0 0 25 5 0 0 0 0 5

    C(4,5 ) = min { 65 , 55 } = > C(4,5) = 55 ; R(4,5) =5

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 1 1 1

  • 5/21/2018 Cap_9-10-11_2010

    29/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    29

    2 0 10 50 2 0 2 3

    3 0 0 30 60 3 0 0 3 3

    4 0 0 0 15 55 4 0 0 0 4 5

    5 0 0 0 0 25 5 0 0 0 0 5

    C(1,3 ) = min { 110 , 110 , 100 } = > C(1,3) = 100 ; R(1,3) = 3

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 100 1 1 1 3

    2 0 10 50 2 0 2 3

    3 0 0 30 60 3 0 0 3 3

    4 0 0 0 15 55 4 0 0 0 4 5

    5 0 0 0 0 25 5 0 0 0 0 5

    C(2,4 ) = min { 115 , 80 , 105 } = > C(2,4) = 80 ; R(2,4) = 3

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 100 1 1 1 32 0 10 50 80 2 0 2 3 3

    3 0 0 30 60 3 0 0 3 3

    4 0 0 0 15 55 4 0 0 0 4 5

    5 0 0 0 0 25 5 0 0 0 0 5

    C(3,5 ) = min { 125 , 125 , 130 } = > C(3,5) = 125 ; R(3,5) = 4

    En caso de que dos costos se repitan y sean mnimos, se escoge aquel que esta asociado alsubndice i mayor.

    Cij 1 2 3 4 5 Rij 1 2 3 4 51 20 40 100 1 1 1 3

    2 0 10 50 80 2 0 2 3 3

    3 0 0 30 60 125 3 0 0 3 3 4

    4 0 0 0 15 55 4 0 0 0 4 5

    5 0 0 0 0 25 5 0 0 0 0 5

    C(1,4 ) = min { 155 , 155 , 130 , 175 } = > C(1,4) = 130 ; R(1,4) = 3

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 100 130 1 1 1 3 3

    2 0 10 50 80 2 0 2 3 3

    3 0 0 30 60 125 3 0 0 3 3 4

    4 0 0 0 15 55 4 0 0 0 4 5

    5 0 0 0 0 25 5 0 0 0 0 5

    C(2,5 ) = min { 205 , 145 , 155 , 160 } = > C(2,5) = 145 ; R(2,5) = 3

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 100 130 1 1 1 3 3

    2 0 10 50 80 145 2 0 2 3 3 3

    3 0 0 30 60 125 3 0 0 3 3 4

    4 0 0 0 15 55 4 0 0 0 4 5

    5 0 0 0 0 25 5 0 0 0 0 5

    C(1,5) = min {245, 245, 195, 225, 230} = > C(1,5) = 195; R(1,5) = 3

  • 5/21/2018 Cap_9-10-11_2010

    30/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    30

    Cij 1 2 3 4 5 Rij 1 2 3 4 5

    1 20 40 100 130 195 1 1 1 3 3 3

    2 0 10 50 80 145 2 0 2 3 3 3

    3 0 0 30 60 125 3 0 0 3 3 4

    4 0 0 0 15 55 4 0 0 0 4 5

    5 0 0 0 0 25 5 0 0 0 0 5

    La construccin del rbol es un proceso recursivo, el cual consiste en tomar los sub ndicesdel primer arreglo y localizarlos en la matriz de races.

    Se asigna el elemento R[1,n] de esa matriz y pasa a ser la raz del ABBO subdividiendo elarreglo en una mitad que representa al sub rbol izquierdo y otra al sub rbol derecho,repitindose este proceso hasta encontrar una matriz de dimensin 1x1, que representara unahoja en el rbol final.

    Rij 1 2 3 4 5

    1 1 1 3 3 3

    2 0 2 3 3 3

    3 0 0 3 3 4

    4 0 0 0 4 5

    5 0 0 0 0 5

    A Bien Con De El

    1 2 3 4 5

    Rij 1 2 3 4 5

    1 1 1 3 3 3

    2 0 2 3 3 3

    3 0 0 3 3 4

    4 0 0 0 4 5

    5 0 0 0 0 5

    Las sub-matrices restantes son de 1x 1 entonces se localizan en el rbol cumpliendo lacondicin de ABB, quedando as el siguiente ABBO.

    Rij 1 2 3 4 5

    1 1 1 3 3 3

    2 0 2 3 3 3

    3 0 0 3 3 4

    4 0 0 0 4 5

    5 0 0 0 0 5

    Con

    A Bien

    1 2

    De El

    4 5

    Con

    A El

    Bien

    2

    De

    4

    Con

    A El

    Bien De

  • 5/21/2018 Cap_9-10-11_2010

    31/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    31

    d) Problemas de optimizacin y algoritmos avaros (greedy)

    En esta seccin estudiaremos varios problemas de optimizacin que se pueden resolverempleando algoritmo codiciosos o estrategia Greedy. Es comn que en los problemas deoptimizacin el algoritmo tenga que tomar una serie de decisiones cuyo efecto general esreducir al mnimo el costo total, o aumentar al mximo el beneficio total, de algn sistema. El

    mtodo codicioso consiste en tomar sucesivamente, las decisiones de modo que cada decisinindividual sea la mejor de acuerdo con algn criterio limitado "a corto plazo" cuya evaluacinno sea demasiado costosa. Una vez tomada una decisin, no se podr revertir, ni siquiera sims adelante se hace obvio que no fue una buena decisin. Por esta razn, los mtodoscodiciosos no necesariamente hallan la solucin ptima exacta de muchos problemas. Noobstante, en el caso de los problemas que se estudiaran en este captulo, es posible demostrarque la estrategia codiciosa apropiadaproduce soluciones ptimas. Tambin se abordaran

    problemas con los que estrategias codiciosas muy similares fracasan.En general la estrategia Greedy trabaja en fases. En cada fase, se realiza una decisin queaparentemente es la mejor, sin considerar o lamentar futuras consecuencias. Generalmente,esta idea es pensada como escoger algn ptimo local. Si se resume la estrategia como "toma

    lo que puedas obtener ahora" podr entender el porque del nombre de esta clase dealgoritmos. Cuando el algoritmo termina tendremos la esperanza que el ptimo local es igualal ptimo global. Si este es el caso, entonces el algoritmo es correcto, de otra manera elalgoritmo a generado una solucin suboptimal. Si la "mejor" respuesta no es requeridaentonces los algoritmos greedy son a menudo usados para generar respuestas aproximadas, envez de usar algoritmos ms complicados que requieren de otra estrategia para generar "la"respuesta correcta. En general la estrategia Greedy trabaja en etapas "Top-Down" realizandouna eleccin greedy despus de la otra. En resumen, la estrategia Greedy consiste de dos

    partes:1. Subestructura Optimal2. Partir con eleccin de ptimos locales y continuar haciendo elecciones localmenteoptimales, hasta que la solucin es encontrada.

    Ejemplos: Problema Arbol Expandido Minimal ( Minimum Spanning Trees)Dado un grafo no-dirigido y conexo G = , donde cada arco tiene asociado una"longitud" o "peso", se desea un subconjunto T, de arcos E, tal que el grafo restante seaconexo si solamente los arcos en T son usados, y la suma de los pesos de los arcos es el ms

    pequeo posible. Tal subconjunto debe formar un subgrafo que es un rbol, al cual se le llamaMinimum Spanning Tree.

    Otro problema: En el proceso de cambio de monedas, por ejemplo $15.530 puede expresarse

    en $15.530 = 1 * $10.000 + 1 * $ 5.000 + 1 * $ 500 + 3 * ($10). En total se requieren 5elementos. Al hacer esto estamos seguro de que el nmero de billetes y monedas es elmnimo.

    Los problemas de trfico son tpicos casos en que las elecciones ptimas locales no siemprefuncionan. Si duda, pregunte en Santiago sobre el resultado de las vas exclusivas que luego

    pasaron a ser vas ..y ahora el transantiago.

    (Problema de Planificacin)

    Dado los trabajos t 1, t 2, ... t n, con tiempos t1, t2, ... tny un solo procesador. Cul es lamejor forma de planificar esos trabajos a fin de minimizar el tiempo medio de terminacin?

  • 5/21/2018 Cap_9-10-11_2010

    32/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    32

    Compresin de archivos. (Cdigo de Huffman)

    Un cdigo de longitud fija de un alfabeto A= { a1, a2, ..., am} con m-letras es una expresinen donde cada letra ai= ci,1ci,2...ci,n, en donde i= 1, ...m, y donde cada c i,j fes un elemento dealgn conjunto de smbolos. El conjunto C= { ci,1ci,2...ci,n , tal que, i= 1, ...m,} es llamadocdigo de longitud fija de longitud n, y cada ci,1ci,2...ci,,nes llamado cdigo.

    Ejemplo:Sea A= { a, b, c, d }, entonces { a= 00, b= 01, c=10, d=11} es un cdigo de longitud fija paraA y { 00, 01, 10, 11} es el cdigo binario de longitud fija de tamao n, donde los smbolos delconjunto es {0, 1].

    Ejemplo: Cdigo ASCII es un cdigo binario de longitud fija de longitud 8. Toda letra ocarcter es codificado con string de 8-bit.

    Por otra parte, un cdigo de longitud variable de un alfabeto A= { a1,a2, ..., am} con m-letrases una expresin en donde cada letra ai= ci,1ci,2...ci, li, en donde i= 1, ...m, y donde cada ci,jfes un elemento de algn conjunto de smbolos. El conjunto C= { c i,1ci,2...ci,,li , tal que, i= 1,

    ...m,} es llamado cdigo de longitud variable, y cada ci,1ci,2...ci, lies llamado cdigo.

    Ejemplo:Sea A= { a, b, c, d }, entonces { a= 0, b= 110, c=10, d=111} es un cdigo de longitud variable

    para A y { 0, 110, 10, 111} es el cdigo binario de longitud variable, donde los smbolos delconjunto son de {0, 1]. Se dice, que un cdigo es prefijo si ningn cdigo es un prefijo dealgn otro.

    Ejemplo:Sea A= { a, b, c, d }, entonces { a= 0, b= 110, c=10, d=111} es un cdigo prefijo, pues alrecibir el mensaje 1100111 tiene una nica decodificacin bad. Por otra parte, si { a= 1, b=110, c=10, d=111}, entonces { 1,110, 10, 111}, no es un cdigo prefijo, pues al recibir elmensaje 110 podra ser decodificado en b o ac.

    El problema es, suponga que tenemos un archivo de dato con 100.000-caracteres que se deseacompactificar, observamos que los caracteres que ocurren con sus respectivas frecuencias son:6 caracteres, a, b, c, d, e y f con frecuencias 45, 13, 12, 16, 9 y 5, respectivamente (en miles).Cul es el cdigo de longitud fija y variable que usa el menor espacio?. Una propuesta es:

    Caracteres a b c d e fFrecuencia 45 13 12 16 9 5

    Cdigo long. Fija 000 001 010 011 100 101Cdigo long. Var. 0 101 100 111 1101 1100

    Para almacenar 100 de estos caracteres,cdigo de long. Fija requiere 100*3 = 300 bits, mientras quecdigo de long. variable requiere 45*1+13*3+12*3+16*3+9*4+5*4=224, ahorrando casi un25%, de manera que podemos en principio afirmar que cdigos de longitud variable sonmejores.

    Dado un alfabeto A con frecuencia de distribucin { f(a), a A}, el cdigo Huffmanconstruye un rbol binario T, donde los nodos consisten de algunas letras de A y algunas

    nuevas letras junto con su frecuencia, las hojas consisten de solamente letras de A, todo nodotiene 2 hijos, hijo izquierdo, rotulado con 0 e hijo derecho rotulado con1. El cdigo para cadaletra es la sucesin de bits rotulados sobre el nico camino desde la raz a la hoja.

  • 5/21/2018 Cap_9-10-11_2010

    33/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    33

    Etapa1: Tomar 2 letras con la frecuencia ms pequea de ocurrencia y crear un subrbol quetiene estos 2 caracteres como hojas.Etapa2: Ahora imaginemos que este subrbol representa un nuevo carcter cuya frecuencia esigual a la suma de las frecuencias de las 2 letras, de manera que se obtiene un nuevo alfabetocon una letra menos. Se repite este proceso, llamada merge, con el nuevo alfabeto hasta que el

    alfabeto tiene una letra.Ejemplo:Sea A= {f/5, e/9, c/12, b/13, d/16, a/45}, el alfabeto con sus frecuencias de distribucin. Elcdigo se obtiene como sigue:

    0 1

    El nuevo alfabeto es A1 = {c/12, b/13, n1/14, d/16, a/45},

    0 1 0 1

    El nuevo alfabeto es A2 = {n1/14, d/16, n2/25, a/45},

    0 1 0 1

    0 1

    El nuevo alfabeto es A 3 = {n2/25, n3/30, a/45}, continuando se obtiene,

    0 1

    0 1 0 1

    0 1

    c/12 b/13 n1/14 d/16

    f/5 e/9

    n1/14 n2/25 a/45

    c/12 b/13f/5 e/9

    a/45

    d/16

    n2/25 n3/30 a/45

    n1/14 d/16c/12 b/13

    f/5 e/9

    a/45 n4/55

    n2/25

    c/12 b/13

    n3/30

    n1/14 d/16

    f/5 e/9

  • 5/21/2018 Cap_9-10-11_2010

    34/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    34

    El nuevo alfabeto es A4 = {n4/55, a/45}, y finalmente se tiene

    0 1

    0 1

    0 1 0 1

    0 1

    El nuevo alfabeto es A5 = {n5/100}. El cdigo Huffman es obtenido desde el rbol binariorotulado. En efecto, a=0, b=101, c= 100, d=111 , e=1101, f= 1100.

    Algoritmo:

    Dado un alfabeto A con distribucin de frecuencia { f(a), a A}, una prioridad Q, clavessobre f, que es usada para identificar las 2 letras con menor frecuencia. Se tiene,

    Huffman(A) {

    n=|A|;Q=A;for i=1 to n-1 {

    z=localizar()x= Izq[z] = Extraer_Min(Q);y= Der[z] = Extraer_Min(Q);

    f[z]= f[x] + f[y];Insertar(Q, z);

    }return Extraer_Min(Q)//raz del rbol binario

    El tiempo de ejecucin es O(nlogn), ya que cada operacin prioridad toma tiempo O(logn).Este algoritmo es para construir el rbol de Huffman, y luego a partir de l construir el cdigode Huffman. Se demuestra que el algoritmo Huffman genera un rbol cdigo prefijo optimal.

    Desde el punto de vista de su implementacin el cdigo Huffman usa "priority_queue" , quees una aplicacin usual de los Heaps, la cola de prioridad es una estructura de datos con slo 2operaciones, Insertar un elemento y eliminar el elemento que tenga la clave ms grande (o

    pequea). Si los elementos tienen claves iguales, la regla habitual establece que el primerelemento introducido deber ser el primero en elimninarse. Por ejemplo, en un sistema decomputo de tiempo compartido, un extenso nmero de tareas pude estar esperando para haceruso de la CPU. En donde algunas de ellas tendrn mayor prioridad que otras, de ah que elconjunto de las que esperan forme una cola de prioridad.

    Propiedades: El elemento que posea la clave mayor est en la cima, y puede extraerse entiempo constante. Sin embargo, tardar tiempo O(log(n)) en restablecer la propiedad de heap

    n5/100

    n4/55

    n2/25

    c/12 b/13

    n3/30

    n1/14 d/16

    f/5 e/9

    a/45

  • 5/21/2018 Cap_9-10-11_2010

    35/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    35

    para el resto de las claves. Ahora si otro elemento ha de insertarse de inmediato, parte de esetiempo puede combinarse con el tiempo O(log(n)) necesario para insertar el nuevo elemento.De esta manera, la representacin de una cola de prioridades como heap resulta ventajoso parun n-grande, ya que se representa eficientemente en el almacenamiento contiguo y segarantiza que slo requerir tiempo algortmico para las inserciones y las eliminaciones.

    Como ya se vi el objetivo es buscar un codigo variable binario apropiado, cuya frecuencia delos datos de entrada sea considerada. El algoritmo de Huffman realiza la codificacin binariacon ayuda de los rboles binarios, que se v de la siguiente manera: Cada nodo tiene un peso,cuyo lugar en el rbol de Codificacin de Huffman esta predeterminado, lo que se logra atravs de "priority_queue" , en donde segn la frecuencia de los smbolos se van disponiendo.Luego, son los nodos de ms baja frecuencia eliminados, para ser reemplazados por un nodointerno que contiene la suma de los nodos internos eliminados. El nuevo nodo es vuelto a

    poner en la priority_queue , este proceso se repite hasta que solamente quede un solo nodo enla la priority_queue como raz del nuevo rbol. Los rtulos de los arcos en el rbol binariodesde la izquierda de su nodo padre se rotula con 0, arcos a la derecha con 1. El rtulo de sushojas es consecuencia de los rotulos de sus arcos sobre el camino desde la raz a la hoja (como

    se puede ver 0000, 001, 1001, etc).Implementacin

    /*Observacin:Esta es una greedy solucion para minimizar el largo del camino externoponderado de un arbol. Como ejemplo se muestra la implementacin decompresin de huffman. Esta solucin usa arboles y priority queue.Ejemplo de uso:

    $ java Cod_Huffman a 45 b 13 c 12 d 16 e 9 f 5

    d=111

    e=1101f=1100b=101c=100a=0

    */

    public class Cod_Huffman {

    public static void main (String[] arg) {

    if (arg.length == 0) {System.out.println ("Use: java Cod_Huffman simbolo frecuencia [simbolo peso ...]");return;

    }

    //formateando la entrada de datosint tamao = arg.length / 2; // numero de items

    PQ queue = new PQ();int peso;char simbolo;Arbol_Peso hoja;

    // incorporando el peso en la priority queuefor (int item=0; item < tamao; item++) {

    peso = Integer.parseInt(arg[item*2 + 1]);simbolo = arg[item*2].charAt(0);

  • 5/21/2018 Cap_9-10-11_2010

    36/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    36

    hoja = new Arbol_Peso (peso,simbolo);queue.insertar(hoja);

    }

    // combina repetidamente los pesos ms pequeos de los rboles,// el rotulo "1" esta a la derecha

    Arbol_Peso chico;Arbol_Peso sig_chico;Arbol_Peso combina;while (! queue.isSingleton()) {

    chico = queue.getMin();sig_chico = queue.getMin();combina = new Arbol_Peso(chico, sig_chico);queue.insertar(combina);

    }

    // print los resultadosprintTabla (queue.getMin(),"");

    }

    public static void printTabla (Arbol_Peso arbol, String prefijo) {if (arbol.izq == null) { // una hoja

    System.out.println(arbol.simbolo()+"="+prefijo);} else {

    printTabla (arbol.der,prefijo+"1");printTabla (arbol.izq, prefijo+"0");

    }}

    }

    //-------------------------------------------------------------// Arboles ponderados para representar cdigo de huffman// inicializacin a travs del constructor Arbol_Peso()

    class Arbol_Peso {private int peso;private char caracter;

    public Arbol_Peso izq;public Arbol_Peso der;

    public Arbol_Peso (int peso, char caracter) {this.peso = peso;this.caracter = caracter;this.izq = null;this.der = null;

    }

    public Arbol_Peso(Arbol_Peso izq, Arbol_Peso der) {this.izq = izq;this.der = der;this.peso = izq.peso + der.peso;

    }

    public int valor () {return this.peso;

    }

    public char simbolo () {return this.caracter;

    }}

  • 5/21/2018 Cap_9-10-11_2010

    37/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    37

    //----------------------------------------------------------------// Una Priority Queue (PQ)(para Arbol_Peso)// usa un loop en vez de una llamada recursiva para mayor rapidez.

    class PQ {private PQnodo primer=null;

    public boolean isSingleton() {return (primer.sig == null);

    }

    public Arbol_Peso getMin () {Arbol_Peso minArbol = primer.arbol;primer = primer.sig;return (minArbol);

    }

    public void insertar(Arbol_Peso newArbol) {primer = insertNodo(newArbol, primer);

    }

    private PQnodo insertNodo (Arbol_Peso newArbol, PQnodo nodo) {if ((nodo==null) || (newArbol.valor()

  • 5/21/2018 Cap_9-10-11_2010

    38/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    38

    Problema de la mochila

    Dado n-objetos y una mochila de capacidad M, en donde el objeto i tiene un peso w i, Se deja

    un porcentaje xi, (0 xi, 1) del objeto i en la mochila, para obtener una ganancia o profit p ixi. El objetivo es entonces completar la carga de la mochila con la mxima ganancia o profitque pueda soportar, y que no exceda la capacidad M.

    Formalmente se desea maximizar

    n n

    (1) p ix i, con la condicin (2) w ix i M, y

    i =1 i =1

    (0 x i1), p i >0, w i >0, e (0 i n).

    De manera que cada conjunto de partes (x1, x2, x3,.... xn) que satisfagan las condiciones (2) y(3) es una posible solucin. Una solucin optimal es una solucin posible, para lo cual lacondicin (1) es un mximo.Existe otra versin del problema llamada versin 0-1 del problema de la mochila, pues noexisten fracciones de las especies, es decir o se toma o se deja. Sin embargo, se puededemostrar que tienen subestructuras optimal, esto es que si eliminamos j- item de las especiesoptimales, el resto debe seguir siendo optimal para W - w j.

    Por ejemplo, para el caso en que n=3 (nmero de objetos), M=20 capacidad de la Mochila, ylos valores (p1 , p2, p3) = (25, 24, 15) y (w1 , w2, w3) = (18, 15, 10),se obtienen 4-posibles soluciones

  • 5/21/2018 Cap_9-10-11_2010

    39/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    39

    (x1 , x2, x3) suma (w ixi) suma(pixi)

    (i) (1/2, 1/3, ) 16.5 24.25(ii) (1, 2/15, 0) 20 28.2(iii) (0, 2/3, 1) 20 31(iv) (0, 1, ) 20 31.5

    es claro que de estas 4-soluciones la (iv) alcanza su mximo profit. Tras este algoritmo semuestra un problema de Optimizacin, en el sentido de hallar la utilidad total ms grande quecualquier subconjunto de los objetos que quepa en la mochila(y hallar un subconjunto que

    produzca la utilidad mxima). As como un problema de Decisin, pues dado k, existe unsubconjunto de los objetos que quepa en la mochila y tenga una utilidad total de por lo menosk?.El problema de la mochila tiene diversas aplicaciones en planificacin econmica y en

    problemas de carga o empaque. Por ejemplo, podra describirse un problema de toma dedecisiones de inversin en el que el tamao de una inversin es la cantidad de dinerorequerida, M es el capital total que se puede invertir y la utilidad de una inversin es el

    rendimiento esperado. Cabe sealar que el problema de la mochila es de maximizacin.

    Implementacin:

    /*Archivo MochilaGreedy.javaEsta es una solucin greedy para el problema de la mochila fraccionario.Los argumentos en la lnea de comando son p1, w1, p2, w2, ..., pn, wn.donde p1 w1 corresponde al valor y peso del objeto1 respectivamente, y assucesivamente.

    Ejemplo de uso:>java MochilaGreedy 25 18 24 15 15 10

    Profit Peso fit24 15 1.015 10 0.525 18 0.0

    Total Profit:31.5*/

    public class MochilaGreedy {private static int maxPeso = 20; // lo que la mochila puede soportar

    public static void main (String[] argumentos) {

    if (argumentos.length == 0) {System.out.println ("Use: java MochilaGreedy profit peso [valor peso ...]");

    return;}

    int tam = argumentos.length / 2; // numero de objetos

    Mochila_objetos [] objs = new Mochila_objetos[tam];float [] fit = new float[tam];

    // ingreso para los objetos en la Mochila// ingresa los datos valor y peso en el objeto array

    int profit;int peso;for (int obj=0; obj < tam; obj++) {

    profit = Integer.parseInt(argumentos[2*obj]);

  • 5/21/2018 Cap_9-10-11_2010

    40/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    40

    peso = Integer.parseInt(argumentos[2*obj+1]);

    objs[obj] = new Mochila_objetos(profit, peso);// creacion de un objetofit[obj] = 0; // ningun objeto en la mochila inicialmente

    }//ordena los objetos en orden decreciente por mtrica//ordenar (objs);

    // hace el manejo (GREEDY)float espacioIzq = maxPeso;int obj=0;while ((espacioIzq>0) && (obj espacioIzq) {

    fit[obj] = espacioIzq / peso;espacioIzq = 0;

    } else {fit[obj] = (float) 1.0;espacioIzq = espacioIzq - peso;

    }obj++;

    }

    displayObjetos(objs, fit);}

    // ---------------------------------------------------------------// display el listado de los datos del objeto

    public static void displayObjetos (Mochila_objetos[] objs, float[] fit){

    // print los datos en este formatoSystem.out.println ("\nProfit\tPeso\tfit");

    float totalProfit=0;int profit;int peso;float suma;

    for (int pos=0; pos < objs.length; pos++) {profit= objs[pos].getProfit();peso= objs[pos].getPeso();suma= fit[pos];totalProfit = (profit*suma) + totalProfit;System.out.println(" "+profit+"\t "+peso+"\t"+fit[pos]);

    }System.out.println("\nTotal Profit: "+totalProfit);

    }

    //---------------------------------------------------------------// sort los objetos en orden decreciente basado en la metricapublic static void ordenar (Mochila_objetos[] array) {

    int ult = array.length - 1;Mochila_objetos temp;

    for (int actual=0; actual < ult; actual++) {for (int obj=actual+1; obj

  • 5/21/2018 Cap_9-10-11_2010

    41/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    41

    }}

    }

    //-------------------------------------------------------------// objetos para representar los objetos de la mochila. Cada uno tiene

    //un profit y un peso como metrica - maximizamos esto en cada etapa del//algoritmo Greedy

    class Mochila_objetos {private int profit;private int peso;private float metrica; // la metrica greedy

    public Mochila_objetos(int profit, int peso) {this.profit = profit;this.peso = peso;

    this.metrica = (float) profit / (float) peso;}

    public int getProfit () {return this.profit;}public int getPeso () {return this.peso;}public float getMetric () {return this.metrica;}

    }

    Existe otra versin considerando que el objeto o se toma o se deja, de ah el considerar 0 o 1,conocido como Knapsack 0-1. Una descripcin formal es: Dados los vectores de valores , y pesos < w1, w2, w3.. wn>, correspondiente a n-objetos, tal que M >0. Sepide determinar el conjunto T{1, 2, 3, 4,...n}, (de objetos a tomar) que logra maximizar

    n

    (1) vi, sujeta a la condicin (2) w i M.i T i T

    La idea que se trabaja en este contexto es la de Programacin dinmica, recordemos que laprogramacin dinmica es un approach para resolver problemas de optimizacin, y es por esoque ve en este contexto. En este contexto se computan las soluciones a los subproblemas unavezy se almacenan en una tabla de manera que ellos puedan ser reutilizadosms tarde.

    Etapa1: Caracterizar la estructura de una solucin optimal(Estructura), es decir descomponerel problema en subproblemas ms pequeos y encontrando en ellos una relacin entre lasestructuras de la solucin optimal al problema original con los problemas ms pequeos.

    Etapa2: Recursivamente se definen los valores de una solucin optimal (Principio deOptimabilidad), es decir expresar la solucin del problema original en trminos de solucionesoptimales de los problemas ms pequeos.

    Etapa3: Computar el valor de una solucin optimal en la forma bottom-up usando laestructura de la tabla. (Computacin Bottom-up )

    Etapa4: Construccin de una solucin optimal desde la informacin computada.(Construccin de la solucin optimal).

    Etapas3 y 4 pueden ser combinadas, sin embargo las etapas 1-3 forman la base a la solucinde problemas va programacin dinmica. Etapa4 puede ser omitida si solamente los valores

  • 5/21/2018 Cap_9-10-11_2010

    42/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    42

    de una solucin optimal son requeridos. En general, la programacin en programacindinmica se refiere al mtodo de la tabla.

    Ejemplo para el caso 0-1, consideremos la fig. XX en donde la fila i representa los objetos, lafila vi los valores y wilos pesos. La matriz V[i, w] es la matriz o tabla en donde se registran

    los clculos, al ver la tabla Ud. notar que la solucin se obtiene en la

    posicin V[4, 10]= 90 que es la solucin optima, cuyos subconjuntos son T ={2, 4}={(4, 40),(3, 50)}.

    Observacin:Basado en el ejemplo anterior y la propuesta siguiente

    Objetos Valor Peso Valor/Peso1 60 10 62 100 20 53 120 30 4

    podr constatar que siendo la capacidad igual a M=50, la solucin greedy seleccionara 1,cuyo capacidad mxima es 60, con un resto de 40 Kg. A este punto, si escogemos los objetos1 y 2 el valor total es 160, y si escogemos los objetos 1 y 3 el valor total es 180. Sin embargo,la solucin optimal se logra al escoger los objetos 2 y 3. De donde el valor total de estasolucin es 220.

    Implementacin

    /*En general se tiene una mochila que puede soportar un peso total M, as como un juego de N

    objetos, en que cada uno tiene un wi de peso y un pi de valor.Los objetos son nicos, en el sentido de incluirlos en la mochila o dejarlos, es decir no tiene

    sentido en este contexto tomar una porcin, porcentaje, parte o mltiplos de la inclusin de unobjeto. Se desea empacar en nuestra mochila los objetos de mayor valor, cuya capacidad total

  • 5/21/2018 Cap_9-10-11_2010

    43/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    43

    Ejemplo de uso

    >java Mochila01 10 5 10 4 40 6 30 3 50

    Capacidad Maxima: 10(5, 10)(4, 40)(6, 30)(3, 50)Subconj -Valores(4, 40) 40(3, 50) 50

    */public class Mochila01 {

    public static void main(String[] args) {int max_capacidad, num_objetos, objs, capacidad, i, longitud, w, cap;

    int valor0, valor1, max_valor, j;int[] peso, valor;int[][] subsoluciones;int[][][] carga;

    // Lee los argumentos de la lnea de comando. El primer

    //argumento es capacidad maxima los siguientes son pares asociados a//(peso, valor) para cada objeto.

    longitud = args.length;max_capacidad = Integer.parseInt(args[0]);num_objetos = (longitud - 1) / 2;peso = new int[num_objetos];valor = new int[num_objetos];subsoluciones = new int[num_objetos][max_capacidad+1];carga = new int[num_objetos][max_capacidad+1][num_objetos];

    for (i=0; i

  • 5/21/2018 Cap_9-10-11_2010

    44/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    44

    carga[objs][cap][j] = carga[objs-1][cap][j];

    if (peso[objs] > cap)subsoluciones[objs][cap] = subsoluciones[objs-1][cap];

    else {valor0 = subsoluciones[objs-1][cap];valor1 = subsoluciones[objs-1][cap - peso[objs]] + valor[objs];

    if (valor0 > valor1) {subsoluciones[objs][cap] = valor0;

    }else {

    subsoluciones[objs][cap] = valor1;for (j=0; j

  • 5/21/2018 Cap_9-10-11_2010

    45/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    45

    EJEMPLO 1:

    Un problema clsico es elproblema del vendedor viajero: Dadas nciudades conectadas todascon todas, encontrar el camino que recorra todas las ciudades con mnimo costo. Se parte deuna ciudad cualquiera, y se obtiene el siguiente espacio de soluciones:

    (1)

    (1,2) (1,3) ....... (1,n)

    (1,2,3) (1,2,n) .......... (1,n,2) ........................

    (1,2,3,4,...,n) En este nivel se tienen todos los posibles caminosjunto con su costo asociado.

    Criterios de poda: cuando se encuentra el primer camino se guarda el camino y su costo comoposiblesolucin. Si se encuentra uno mejor se redefine la solucin. Si por una rama se detectaque el costo parcial esmayoral costo de la solucin alcanzada hasta el momento, entonces

    podoese subrbol (pero no a sus hermanos).

    EJEMPLO 2:

    Dada una secuencia de nenteros, se desea saber si existe una particin en dos subconjuntosS1 y S2 disjuntos, tal que la suma de sus elementos sea la misma, es decir:

    Dado S= {s1,s2,...,sn}

    Se desea encontrar dos subconjuntos S1 y S2tal que: S1S2 = y sj = si

    jS1 iS2

    Esta particin podra existir como no. Analicemos todo el espacio de soluciones para unejemplo concreto:

    S={2, 3, 4, 5, 9, 6, 7 }S1= {2, 3, 4, 9}S2= {5, 6, 7}

    S

    S1= {2} {3} ... {7}S2= {3,4,5,9,6,7} {2,4,5,9,6,7} {2,3,4,5,9,6}

    {2,3} {2,4} ... {2,7} ... {7,2} ... {7,6}{4,5,9,6,7} {3,5,9,6,7} {3,4,5,9,6} {3,4,5,9,6} {2,3,4,5,9}

    ... ... ... ... ...{2,3,4} {5,9,6,7}

  • 5/21/2018 Cap_9-10-11_2010

    46/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    46

    1nivel 12nivel n.... ....

    n(n-1)... n! O(nn)Sobre esto pueden hacerse mejoras:

    - Evitar generar los mismos subconjuntos: Se puede observar en el rbol que algunasparticiones estn repetidas, por ejemplo {2,7}{3,4,5,9,6} y {7,2}{3,4,5,9,6}. Para evitaresto se podran ordenar los elementos de menor a mayor antes de empezar la bsqueda, yluego si se tiene {7,2}y vemos que 7 >2, esta particin ya fue hecha y seguir en esta ramasera en vano, por lo que se abandona la bsqueda en esa rama, y de esta manera se va

    podando el rbol.

    EJEMPLO 3:

    Otro tipo de aplicaciones de Backtracking son los juegos. Considere juegos tales como elajedrez, damas, donde hay dos jugadores. Los jugadores alternan sus movimientos, y el estadodel juego puede ser representado por la posicin del tablero. Se asume que hay un nmero

    finito de posiciones en el tablero y que el juego tiene alguna regla que asegure su terminacin.Con cada juego asociamos un rbol llamado rbol del juego. Cada nodo en el rbol representauna posicin en el tablero. A la raz le asociamos la posicin de comienzo. Si la posicin xest asociada con el nodo n, luego los hijos de n corresponden al conjunto de movidas

    permitidas desde la posicin x, y con cada hijo es asociada la posicin del tablero resultante.Por ejemplo la siguiente figura muestra parte del rbol del tic tac toe:

    juega A

    ... . . . . . .

    juega A

    juega B

    juega A

    A A A B

    B B

    A A A

    A B

    B B

    A A

    A A B

    B B

    A A A B

    B A B

    A B A

    A A B

    B B

    A A

    A A B

    B B B

    A B A

    A A B

    B A B

    A B A A B

    B A B

    A A

    B A B

    B A B

    A B AA A B

    B A B

    A A A

    B A B

    B A B

    0 0

    0 0 1

    -1 0

    -1

    1

    1

    1

    0

  • 5/21/2018 Cap_9-10-11_2010

    47/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch F.

    ____________________________________________________________________Ingeniera en Computacin, Universidad de La Serena

    47

    Las hojas de un rbol de juego corresponden a las posiciones del tablero donde no hay msmovimientos, porque uno de los jugadores ha ganado o todos los casilleros estn llenos y aocurrido un empate. Se asocia un valor a cada nodo del rbol. Primero se asignan valores a lashojas planteado desde el punto de vista de uno de los jugadores, tomemos A. Los valoressern -1, 0 o 1, si A pierde, gana o empata respectivamente. Los valores se propagan hacia

    arriba en el rbol de acuerdo a la siguiente regla: Si un nodo corresponde a la posicin del tablero donde le toca jugar a A, luego el valor con

    el que se rotura este nodo es el mximode los valores de los hijos de este nodo. Es decir, seasume que A har el movimiento ms favorable para s, el cual produce el valor ms alto.

    Si el nodo corresponde a un movimiento de B, el valor con el que rotulamos es el mnimode los valores de sus hijos. Es decir, se asume que B mover inteligentemente, tratando deganarle a A o por lo menos empatar.

    Al terminar el backtracking, se distinguen tres situaciones:1. Si la raz tiene un valor 1, el jugador A tiene una estrategia ganadora. Cuando comienza

    tiene la garanta de que puede seleccionar un movimiento que lo lleva a la posicin deltablero de valor 1. Cuando es el turno del jugador B, ste no tiene mas eleccin que unmovimiento que lo conduce a la posicin del tablero de valor 1, una prdida para l. Elhecho de que un juego termine, garantiza una eventual ganancia para el primer jugador.

    2. Si la raz tiene valor cero, como en el caso del ta-te-ti, luego ninguno de los jugadorestiene una estrategia ganadora, solo puede garantizarse a si mismo, empatar jugando tan

    bien como sea posible.3. Si la raz es -1, el jugador B tiene una estrategia ganadora.

    El siguiente algoritmo determina si existe una estrategia ganadora para A, teniendo en cuentaque:

    B juega inteligentemente. El estado es el tablero, hay que distinguir si el nivel es mx o mn, segn juegue A o B

    respectivamente.

    Hay tres situaciones: A gana (1), A pierde (-1), A empata (0). Un nodo es una hoja si se da una de las situaciones mencionadas anteriormente. Poda: si el estado corresponde al nivel de mximo y en un hijo retorna un 1, ya no puede

    superarse, se tiene una estrategia ganadora, no se necesita buscar ms (no se necesitarecorrer sus hermanos), entonces: se poda. En el ejemplo del rbol del ta-te-ti, el primerhijo retorna un 1, por lo tanto no hay necesidad de generar sus hermanos. De la mismaforma, si el estado corresponde al nivel de mnimo, si se obtiene un -1, encuentre lo que

    encuentre ms adelante el mnimo ser -1, entonces se podan los hermanos.

    Geometra Computacional

    La geometra computacional se encarga del diseo y anlisis de algoritmos para resolverproblemas geomtricos. Los algoritmos geomtricos eficientes son muy utilizados en camposcomo la computacin grfica, la estadstica, el procesamiento de imgenes y en el diseo conintegracin a muy grande escala, tambin llamado (very-large-scale-integration, VLSI).

    Algoritmo para calcular la cubierta convexa.

    Uno de los problemas fundamentales en la geometra computacional es el de calcular los

    puntos que "acotan" a un conjunto finito de puntos en el plano, formalmente llamado,cubierta convexa.

  • 5/21/2018 Cap_9-10-11_2010

    48/54

    Diseo y Anlisis de Algoritmos con Java Dr.Eric Jeltsch