Divide y Venceras
December 2, 2022 | Author: Anonymous | Category: N/A
Short Description
Download Divide y Venceras...
Description
Cuestiones generales La té técn cnic ica a de di dise seño ño de al algo gori ritm tmos os ll llam amad ada a "d "div ivid ide e y ve venc ncer erás ás"" (divide and conquer) consiste en descomponer el problema original en va vario rios s su sub-p b-pro roble blemas mas más sen sencil cillos los,, par para a lue luego go resol resolve verr és éstos tos mediante un cálculo sencillo. Por ltimo, se combinan los resultados de cada sub-problema para obtener la soluci!n del problema original. l pseudoc!digo ser#a$ funcion divide_y_venc divide_y_venceras_1(problem eras_1(problema) a) { descomponer el problema en n subproblemas más pequeños; para i=1 hasta n hacer resolver el subproblema k; combinar las n soluciones;
%n e&emplo de "divide y vencerás" es el quic'sort. n ella, se divid#a el arr arregl eglo o en do dos s sub sub-a -arre rreglo glos, s, para para lue luego go resol resolve verr cad cada a uno por separado, y unirlos. l tiempo necesario para ordenar un arreglo de elementos mediante el método de la burbu&a es cuadrático$ ' . *i dividimos el arreglo en dos y ordenamos cada uno de ellos, el tiempo nece ne cesa sari rio o pa para ra re reso solv lver erlo lo es a+ a+or ora a '( '( ) )'()('). l tiem ti empo po ne nece cesa sari rio o pa para ra orde ordena narl rlo o es la mi mita tad, d, pe pero ro si sigu gue e si sien endo do cuadrático. Pero a+ora, si los subproblemas son todav#a demasiado grandes, /por qué no utili0ar la misma táctica con ellos, esto es, dividirlos a ellos también, utili0ando un algoritmo recursivo que vaya dividiendo más el sub-problema sub-problem a +asta que su soluci!n sea trivial1 %n algoritmo del tipo$ funcion divide_y_venc divide_y_venceras(problema) eras(problema) { si el problema es trivial entonces resolver el problema; si no es trivial { descomponer el problema en n subproblemas más pequeños; para i=1 hasta n hacer divide_y_venceras(subproblema_k); combinar las n soluciones;
*i aplicamos este método al quic'sort, el tiempo disminuye +asta ser logar#tmico, con lo que el tiempo a+orrado es mayor cuanto más aumenta .
Divide y Venceras
1
Tiempo de ejecución l tiempo de e&ecuci!n de un algoritmo de divide y vencerás, 2(n), viene dado por la suma de dos elementos$ l tiempo que tarda en resolver los 3 subproblemas en los que se divide el original, 342(n5), donde n5 es el tamaño de cada sub-
problema. l tiempo necesario para combinar las soluciones de los subproblemas para +allar la soluci!n del original6 normalmente es 7(n ')
Por tanto, el tiempo total es$ 2(n) 342(n5) 7(n '). La soluci!n de esta ecuaci!n, si 3 es mayor o igual que 8 y 5 es mayor que 8, es$ si 395', 2(n) 7(nlog53) si 35', 2(n) 7(n'4log n) si 3:5', 2(n) 7(n')
Determinación del umbral Determinación %no de los aspectos que +ay que tener en cuenta en los algoritmos de divide y vencerás es d!nde colocar el umbral, esto es, cuándo se consider cons idera a que un subsub-prob problema lema es su;ic su;icient ienteme emente nte pequ pequeño eño como para no tener que dividirlo para resolverlo. ormalmente esto es lo que +ace que un algoritmo de divide y vencerás sea e;ectivo o no. Por e&emplo, en el algoritmo de ordenaci!n quic'sort, cuando se tiene un array de longitud { au.=array5i6; ++ Kntercambiar# Kntercambiar # array5i6=array5d6; array5d6=au.; else ++ si se han cruCado> break; ++ salir del bucle# if(d==desdeE1) if(d==desdeE1) ++ Ai la se%unda b-squeda se sale del array d=desde; ++ es que el pivote es el elemento ++ más pequeño> se cambia con Ll mismo# au.=array5d6; ++ olocar el pivote array5d6=array5desde6; array5d6=arra y5desde6; ++ en su posiciHn# array5desde6=au.;
if(d==k) return(array5d6); return(array 5d6); ++ /l pivote es el elemento buscado else if(d$k)
return(seleccionrapida(a return(selec cionrapida(arraydesdedE rraydesdedE1)); 1)); ++ Fuscar en el primer array# else return(seleccionrapida(a return(selec cionrapida(arrayd:1hast rrayd:1hasta)); a)); ++ Fuscar en el se%undo array#
n es esta ta so solu luci ci!n !n en ti tiem empo po me medi dio o li line neal al se de desc scar arta tan n s! s!lo lo un unos os cuanto cua ntos s ele eleme mento ntos s cad cada a ve ve0 0 que se lla llama ma a la ;un ;unci! ci!n n re recur cursiv siva, a, depen dep endie diendo ndo de dell pivote pivote que eli&a eli&amo mos. s. Pa Para ra des descar cartar tar una ;ra ;racci cci!n !n constante de elementos (y me&orar el tiempo de e&ecuci!n del peor caso) +abr#a que elegir un me&or pivote, a ser pre;erible la mediana (cosa que no puede ser, porque es &ustamente ella la que estamos buscando). 2ampoco se puede perder muc+o tiempo en buscar un buen pivote, porque +ar#a demasiado lento el programa. %na opci!n ser#a elegir tres elementos y utili0ar como pivote la mediana de esos tres, pero en el peor caso eso sigue siendo una mala opci!n. @ay un algoritmo de elecci!n del pivote llamado "partici!n con base en la mediana de la mediana de cinco", que consiste en$ •
•
•
?iv ivid idir ir los los n eleme lemen ntos tos en nA gr grup upos os de A ele leme men ntos tos (ignorando los ltimos elementos). ncontrar la mediana de cada grupo de A elementos, lo que da una lista de nA medianas B. @allar la mediana de B, o un buen pivote en B, lo que se puede +acer utili0ando este algoritmo recursivamente.
Divide y Venceras
7
*e puede probar que, utili0ando este método, y en el peor de los casos, cada llamada a la ;unci!n recursiva desprecia a más del i >ili liar ar pa para ra la bsqueda del pivote. l problema completo ser#a$ !include "stdio#h$ !include "stdlib#h$ !include "strin%#h$ int seleccionrapida(int 0int 0intintint); int hallamediana(int 0int 0int); int main() { int numamk; int 0array0pos;
scanf(7 8d79num); ++ 3edir el tamaño del array array=(int 0)malloc(siCeof(int)0num 0)malloc(siC eof(int)0num); ); for(a=;a"num;a::) for(a=;a"num;a::) ++ ar valores al array scanf(7 8d79array5a6); 8d79array5a6); scanf(7 8d79k); ++ 3edir el valor k kEE;
pos=(int 0)malloc(siCeof(int)0num 0)malloc(siC eof(int)0num); );
m=seleccionrapida(arrayp m=seleccionra pida(arrayposnumE1k) osnumE1k); ; ++ 3ara llamar a la funciHn
printf(78d@n7m);
return(); int seleccionrapida(int 0arrayint 0posint desdeint hastaint k) { int idau.; ++ i realiCa la b-squeda de iCquierda a derecha ++ y D realiCa la b-squeda de derecha a iCquierda#
++ { au.=array5i6; ++ Kntercambiar# Kntercambiar # array5i6=array5d6; array5d6=au.;
else ++ si se han cruCado> break; ++ salir del bucle#
Divide y Venceras
8
if(d==desdeE1) if(d==desdeE1) ++ Ai la se%unda b-squeda se sale del array d=desde; ++ es que el pivote es el elemento ++ más pequeño> se cambia con Ll mismo# au.=array5d6; ++ olocar el pivote array5d6=array5desde6; array5d6=arra y5desde6; ++ en su posiciHn# array5desde6=au.;
if(d==k) return(array5d6); return(array 5d6); ++ /l pivote es el elemento buscado else if(d$k) return(seleccionrapida(a return(selec cionrapida(arrayposdesd rrayposdesdedE1k)); edE1k)); ++ Fuscar en el primer array# else return(seleccionrapida(a return(selec cionrapida(arrayposd:1 rrayposd:1hastak)); hastak)); ++ Fuscar en el se%undo array# int hallamediana(int 0arrayint 0posint num) { int a0array2bcd; a0array2bc d; if(num"M) ++ Ai hay menos de M elementos return(pos56); return(pos5 6); ++ vale el primero (lo que devuelve esta ++ funciHn es el 4ndice de la mediana en la variable 7array7 de la funciHn funciHn#
++ seleccionrapida seleccionrap ida que llama por primera veC a esta
++ to (3*EHH) con nombre B%L2 B%L2..K*, que contendrá una secuencia de m l#neas con el resultado de las multiplicaciones$ La l#nea ' del arc+ivo de salida representa la multiplicaci!n de los enteros contenidos en las l#neas ' y '8 del arc+ivo de entrada. Los enteros se representan también como una cadena de caracteres (d#git (d# gitos os po posib sible lemen mente te pre prece cedid didos os del sig signo no I-I). I-I). Lo Los s re resul sultad tados os no pueden tener ceros super;luos a la i0quierda.
Divide y Venceras
15
Ejemplo de entrada ? E12NMQPPQW 1TMWPTQ ?NM N2 2?
Ejemplo de salida E1?M2TP?QN1N?WNQ? 1NNW
Divide y Venceras
16
View more...
Comments