Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Divide y Venceras
Divide y Venceras
funcion divide_y_venceras_1(problema)
{
descomponer el problema en n subproblemas más pequeños;
para i=1 hasta n hacer
resolver el subproblema k;
combinar las n soluciones;
}
funcion divide_y_venceras(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;
}
}
Divide y Venceras 1
Tiempo de ejecución
Uno de los aspectos que hay que tener en cuenta en los algoritmos
de divide y vencerás es dónde colocar el umbral, esto es, cuándo se
considera que un sub-problema es suficientemente pequeño como
para no tener que dividirlo para resolverlo. Normalmente esto es lo
que hace que un algoritmo de divide y vencerás sea efectivo o no.
Por ejemplo, en el algoritmo de ordenación quicksort, cuando se tiene
un array de longitud 3, es mejor ordenarlo utilizando otro algoritmo
de ordenación (con 6 comparaciones se puede ordenar), ya que el
quicksort debe dividirlo en dos sub-arrays y ordenar cada uno de
ellos, para lo que utiliza más de 6 comparaciones.
Divide y Venceras 2
Problema de los puntos más cercanos
sqrt[(xi-xj)2+(yi-yj)2].
Una primera solución podría ser mirar todos los pares de puntos y
quedarse con el más pequeño; al haber n·(n-1)/2 pares de puntos, el
tiempo de ejecución es de O(n 2). El programa resultante es muy
corto, y rápido para casos pequeños, pero al ser este procedimiento
una búsqueda exhaustiva, debería haber un algoritmo más rápido.
Divide y Venceras 3
puntos distribuidos uniformemente, el número de puntos que caen en
esa franja es sqrt(n), así que con una búsqueda exhaustiva el
tiempo de ejecución sería de O(n), y tendríamos el problema
resuelto. El tiempo de ejecución sería, según lo dicho en el otro
apartado, O(n·log n).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main()
{
int a,num;
double x,y;
struct punto p[MAX];
Divide y Venceras 4
for(scanf(" %d",&num),a=0;a<num;a++) // Coge la entrada
{
scanf(" %lf %lf",&x,&y);
p[a].x=x;
p[a].y=y;
}
return(0);
}
Divide y Venceras 5
#include <stdio.h>
#include <stdlib.h>
int k;
int main()
{
int num,a,m;
int *array;
printf("%d\n",m);
return(0);
}
Divide y Venceras 6
// y j realiza la búsqueda de derecha a izquierda.
if(d==k)
return(array[d]); // El pivote es el elemento buscado
else if(d>k)
return(seleccionrapida(array,desde,d-1)); // Buscar en el primer
array.
else
return(seleccionrapida(array,d+1,hasta)); // Buscar en el
segundo array.
}
Divide y Venceras 7
de los elementos. Esto hace que el algoritmo de selección rápida sea
lineal, a pesar de que utilizamos un algoritmo auxiliar para la
búsqueda del pivote. El problema completo sería:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int num,a,m,k;
int *array,*pos;
pos=(int *)malloc(sizeof(int)*num);
printf("%d\n",m);
return(0);
}
Divide y Venceras 8
d=desde; // es que el pivote es el elemento
// más pequeño: se cambia con él mismo.
aux=array[d]; // Colocar el pivote
array[d]=array[desde]; // en su posición.
array[desde]=aux;
if(d==k)
return(array[d]); // El pivote es el elemento buscado
else if(d>k)
return(seleccionrapida(array,pos,desde,d-1,k)); // Buscar en el
primer array.
else
return(seleccionrapida(array,pos,d+1,hasta,k)); // Buscar en el
segundo array.
}
Divide y Venceras 9
Multiplicación de matrices
int i,j,k;
int A[n][n],B[n][n],C[n][n];
// Dar valores a A y B.
for(i=0;i<n;i++)
for(i=0;i<n;i++)
{
C[i][j]=0;
for(i=0;i<n;i++)
C[i][j]+=A[i][k]*B[k][j];
}
Divide y Venceras 10
para las que se necesitan 7 multiplicaciones diferentes, y ahora se
calculan las submatrices de C utilizando sólo sumas:
C1,1 = M1 + M2 - M4 + M6
C1,2 = M4 + M5
C2,1 = M6 + M7
C2,2 = M2 - M3 + M5 - M7
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int max(int,int);
int **multiplicamatriz(int **,int **,int); // Función recursiva que
multiplica matrices
int **suma(int **,int **,int); // suma de matrices
int **resta(int **,int **,int);// Resta de matrices
void libera(int **,int); // Libera memoria
int main()
{
int **mapa1,**mapa2,**sol;
int f1,c1,f2,c2,a,b,m,m1;
Divide y Venceras 11
{
mapa2[a]=(int *)malloc(sizeof(int)*m);
memset(mapa2[a],0,sizeof(int)*m);
}
for(a=0;a<f2;a++) // Se cogen los datos de la segunda matriz.
for(b=0;b<c2;b++)
scanf(" %d",&mapa2[a][b]);
sol=multiplicamatriz(mapa1,mapa2,m); // Se multiplican.
return(0);
}
if(num==1)
{
sol[0][0]=mapa1[0][0]*mapa2[0][0];
return(sol);
}
// Crear las submatrices de A y B.
for(q=0;q<2;q++)
{
for(w=0;w<2;w++)
{
A[q][w]=(int **)malloc(sizeof(int *)*(num/2));
for(a=0;a<num/2;a++)
{
A[q][w][a]=(int *)malloc(sizeof(int)*(num/2));
for(r=0;r<num/2;r++)
A[q][w][a][r]=mapa1[a+(num/2)*q][r+(num/2)*w];
}
Divide y Venceras 12
}
// Hallar las matrices M.
f1=resta(A[0][1],A[1][1],num/2);
f2=suma(B[1][0],B[1][1],num/2);
M[1]=multiplicamatriz(f1,f2,num/2);
libera(f1,num/2);
libera(f2,num/2);
f1=suma(A[0][0],A[1][1],num/2);
f2=suma(B[0][0],B[1][1],num/2);
M[2]=multiplicamatriz(f1,f2,num/2);
libera(f1,num/2);
libera(f2,num/2);
f1=resta(A[0][0],A[1][0],num/2);
f2=suma(B[0][0],B[0][1],num/2);
M[3]=multiplicamatriz(f1,f2,num/2);
libera(f1,num/2);
libera(f2,num/2);
f1=suma(A[0][0],A[0][1],num/2);
f2=B[1][1];
M[4]=multiplicamatriz(f1,f2,num/2);
libera(f1,num/2);
f1=A[1][1];
f2=resta(B[0][1],B[1][1],num/2);
M[5]=multiplicamatriz(f1,f2,num/2);
libera(f2,num/2);
f1=A[1][1];
f2=resta(B[1][0],B[0][0],num/2);
M[6]=multiplicamatriz(f1,f2,num/2);
libera(f2,num/2);
f1=suma(A[1][0],A[1][1],num/2);
f2=B[0][0];
M[7]=multiplicamatriz(f1,f2,num/2);
libera(f1,num/2);
C[0][0]=suma(M[1],M[2],num/2);
aux=C[0][0];
C[0][0]=resta(C[0][0],M[4],num/2);
aux2=C[0][0];
C[0][0]=suma(C[0][0],M[6],num/2);
libera(aux,num/2);
libera(aux2,num/2);
C[0][1]=suma(M[4],M[5],num/2);
C[1][0]=suma(M[6],M[7],num/2);
C[1][1]=resta(M[2],M[3],num/2);
aux=C[1][1];
C[1][1]=suma(C[1][1],M[5],num/2);
aux2=C[1][1];
C[1][1]=resta(C[1][1],M[7],num/2);
libera(aux,num/2);
libera(aux2,num/2);
Divide y Venceras 13
for(a=1;a<=7;a++)
libera(M[a],num/2);
// Unir las submatrices de matrices C en sol.
for(q=0;q<num;q++)
for(w=0;w<num;w++)
sol[q][w]=C[q/(num/2)][w/(num/2)][q%(num/2)][w%(num/2)];
// Liberar las submatrices de A, B y C.
for(q=0;q<2;q++)
for(w=0;w<2;w++)
{
libera(A[q][w],num/2);
libera(B[q][w],num/2);
libera(C[q][w],num/2);
}
return(sol);
}
Divide y Venceras 14
Multiplicación de dos enteros
Objetivo
Entrada
Salida
Divide y Venceras 15
Ejemplo de entrada
3
-0124576679
10859687
00345
42
0
23
Ejemplo de salida
-1352863741439473
14490
0
Divide y Venceras 16