Estrategias de programación
Divide y vencerás
Programación Dinámica
Divide y vencerás
- Divide el problema en subproblemas que son instancias más pequeñas del mismo problema.
- Vence los subproblemas resolviéndolos recursivamente.
- Combina las soluciones de los subproblemas para obtener la solución del problema original.
Ejemplo: Ordenamiento por mezcla
template<typename T_>
void mergeSort(T_ arr[], int low, int high)
{
if(low < high)
{
int mid = (low + high)/2;
// Ordenar recursivamente
// las mitades del arreglo
mergeSort(arr, low, mid);
mergeSort(arr, mid + 1, high);
// Mezclar las mitades del
// arreglo ordenadas
merge(arr, low, mid, high);
}
}template<typename S_>
void merge(S_ arr[], int low, int mid, int high)
{
S_ *b = new int[high - low + 1];
int h = low;
int i = 0;
int j = mid +1;
// Mezcla las dos mitades ordenadas en
// interaciones anteriores
while(h <= mid && j <= high)
{
if(arr[h] <= arr[j])
{
b[i] = arr[h];
++h;
}
else
{
b[i] = arr[j];
++j;
}
++i;
}
// Completa el arreglo con
// los valores restantes
if(h > mid)
{
for(int k = j; k <= high; ++k)
{
b[i] = arr[k];
++i;
}
}
else
{
for(int k = h; k <= mid; ++k)
{
b[i] = arr[k];
++i;
}
}
// Mover la parte ordenada
// al arreglo original
memcpy(arr + low, b,
(high - low + 1) * sizeof(S_));
delete[] b;
}Teorema maestro
- Caso base: T(n) <= a para todo n lo suficientemente menor.
- Para todo n mayor: T(n) <= aT(n/b) + O(n^d)
donde:
a = número de llamadas recursivas (>= 1)
b = el factor de reducción de los datos de entrada (> 1)
d = exponente del tiempo de ejecución en el paso de combinación (>= 0)
Entonces:
T(n) =
O(n^d log n)
O(n^d)
O(n^(log_b a))
Si a = b^d (caso 1)
Si a < b^d (caso 2)
Si a > b^d (caso 3)
Aplicación del teorema maestro: Mergesort
- a = 2 se hacen 2 llamadas recursivas antes de combinar.
- b = 2 se divide en subroblemas de n/2
- d = 1 tiempo de ejecución O(n) al combinar.
a = b^d (caso 1), entonces: T(n) = O(n log n)
Programación dinámica
Consiste en dividir el problema en subproblemas más pequeños y simples hasta llegar a un punto donde la solución del problema es trivial.
Se utiliza principalmente cuando en la resolución de los subproblemas recursivamente se pueden traslapar las soluciones.
Ejemplo: Dijkstra's shortest path algorithm
Dado un conjunto de nodos, sus caminos y el costo de recorrer estos caminos, encontrar el camino más corto y con menos costo entre dos nodos.
Divide y vencerás - Programación dinámica
By Victor Romero
Divide y vencerás - Programación dinámica
- 772