Professional Documents
Culture Documents
GRUPO: “A”
AREQUIPA – PERU
2017
ADA Página 1
INDICE
1. RESUMEN
2. INTRODUCCION
3. DESARROLLO
4. RESULTADOS
5. CONCLUSIONES
6. BIBLIOGRAFIA
7. ANEXOS
ADA Página 2
1. RESUMEN
El problema de Rod Cutting se basa en que dada una varilla de cierta longitud (entera) y una tabla
de precios para cada posible tamaño de corte, se debe determinar la ganancia máxima que se
puede obtener al cortar la varilla y vender las piezas, además debemos recordar que una solución
óptima podría ser al no realizar ningún corte.
Para dar solución a este problema se hace uso de la técnica de programación dinámica, donde se
utiliza la recursión para poder hallar la ganancia máxima a través de una ganancia optima parcial.
Este informe describe el uso de la técnica de programación dinámica para la solución del problema
de Rod Cutting.
ADA Página 3
2. INTRODUCCION
La Programación Dinámica no sólo tiene sentido aplicarla por razones de eficiencia, sino porque
además presenta un método capaz de resolver de manera eficiente problemas cuya solución ha
sido abordada por otras técnicas y ha fracasado.
Para que un problema pueda ser abordado por esta técnica ha de cumplir dos condiciones:
ADA Página 4
3. DESARROLLO
Serling Enterprises compra varillas largas de acero y las corta en varillas más pequeñas, las cuales
posteriormente las vende obteniendo ingresos. Se desea saber la mejor forma de cortar las
varillas.
Asumimos que sabemos el precio pi que la empresa cobra por una varilla de longitud i pulgadas.
Longitud i 1 2 3 4 5 6 7
Precio pi 1 5 8 9 10 16 17
Dada una varilla de longitud n pulgadas y una tabla de precios pi (donde i = 1, 2, ..., n), determinar
el máximo ingreso rn que se puede obtener cortando la varilla y vendiendo las piezas.
r = 10+1+1= 12
10 1 1
0
rn = 12
ADA Página 5
Con varillas de longitud: 1-3-1-1
r = 1+8+1+5 =15
1 8 1 5
rn = 15
Con una varilla de longitud: 7
r = 17
1
7
rn = 17
Solución óptima:
r max= 5+5+8= 18
5 5 8
rn = 18
En cuántas formas distintas podemos cortar una varilla de longitud n
En primer lugar, debemos saber que para toda varilla de longitud n, se puede realizar un número
máximo de n-1 cortes.
Luego podemos tomar la decisión de realizar o no el corte según nos sea conveniente, por lo tanto
para una varilla de longitud n donde se pueden realizar n-1 cortes hay la posibilidad de realizar o
el corte esto lo podemos tomar como un (0 o 1), por ejemplo si la varilla es de longitud 3 ,se
pueden realizar n-1= 2 cortes, así podemos calcular la variedad de posibilidades mediante la
ADA Página 6
combinación 00,01,10,11, donde 00 significa que la varilla no ha sido cortada, 01 que se ha
realizado un corte en la posición 2, 10 que se ha realizado un corte en la posición 1 y así
sucesivamente.
Mediante esta demostración nos damos percatamos que en número total de combinaciones que
podemos realizar es: 2n-1
a) b) c) d)
e) f) g) h)
Hay 𝑛 − 1 posiciones de corte, y se debe escoger 0 ≤ 𝑘 ≤ 𝑛 − 1 cortes
Al aplicar este algoritmo debemos calcular todas las posibles combinaciones y retornar la que de la
mayor suma, este algoritmo resuelve el problema, pero no es eficiente porque si calculamos su
tiempo de ejecución éste es de orden exponencial T(n)= Θ (2n) que es bastante caro.
Con lo cual queda demostrado que debemos utilizar otro algoritmo para resolver el problema.
Notación Aditiva:
7=2+2+3
𝑛 = 𝑖1 + 𝑖2 + ⋯ + 𝑖𝑘
ADA Página 7
La solución óptima final estaría compuesta por una solución óptima parcial anterior más la varilla
(i) seleccionada. El máximo ingreso rn que se podrá obtener después de encontrar el mayor valor
entre todas las posibles soluciones compuestas por el precio de la varilla de tamaño i (pi) más una
solución óptima anterior.
𝑝1 + 𝑟𝑛−1
𝑝2 + 𝑟𝑛−2
𝒎𝒂𝒙
𝑝𝑛−1 + 𝑟1 𝑟𝑛 = (𝑝 + 𝑟𝑛−𝑖 )
1≤𝑖≤𝑛 𝑖
𝑝𝑛
𝑟𝑛 = 𝑝𝑖 + 𝑎 con a = 𝑟𝑛−𝑖
Implementación
ADA Página 8
¿Por qué es ineficiente?
Porque como vemos en el grafico existen muchos subárboles que vuelven a ser calculados varias
veces, lo cual no sería necesario si utilizamos un arreglo auxiliar para almacenar los valores
calculados.
𝑛 = 0, 1
𝑛
𝑇(𝑛) = {
𝑛 ≥ 1, 1 + ∑ 𝑇(𝑛 − 𝑖)
𝑖=1
𝑇(𝑛) = 2𝑛
La solución óptima se calcula a través de ir calculando el mayor precio de las pequeñas soluciones.
ADA Página 9
Solución aplicar memorización para subárboles ya calculados:
Se llena una tabla con números negativos puesto que la ganancia no puede ser negativa y siempre
va a ser mayor a 0, luego cada vez que se calcula un valor, éste se guarda en la tabla para ser
posteriormente utilizado si vuelve a ser evocado.
Donde:
T(n)=θ(n2)
ADA Página 10
Ejemplo: Hallar el máximo ingreso con una varilla de tamaño 4
Longitud i 1 2 3 4
Precio pi 1 5 8 9
C-r(p,4)
2. Se desarrolla la recursión hasta llegar al caso base (n=0) luego se empieza a resolver la recursión
y se guarda el mayor valor obtenido entre las opciones que se tenga.
C-r(p,4)
1+C-r(p,0) 0 0
ADA Página 11
3. Se utiliza la memorizacion para guardar los valores de subproblemas ya calculados, siempre
guardando el valor maximo.
C-r(p,4)
Max( )
i 0 1 2 3 4
4. Finalmente tomamos como solucion el mayor valor de todas las opciones calculadas
Solución óptima:
C-r(p,4)
Max( )
i 0 1 2 3 4
r[n] 0 1 5 8 10
Solución: El máximo ingreso que se puede obtener para la varilla de tamaño 4 es 10$.
ADA Página 12
4. RESULTADOS
Como resultado hemos comprobado que, al aplicar la técnica de programación dinámica con
memorización, ésta nos ayuda a reducir el tiempo de ejecución en comparación con la solución
iterativa (algoritmo de fuerza bruta) y la solución de programación dinámica sin memorización.
Al realizar el análisis del tiempo de ejecución de los algoritmos que solucionan este problema
podemos verificar que el algoritmo de fuerza bruta es más caro θ(2n) luego está el de top down
θ(n2) y finalmente el de botton up 0(n2).
ADA Página 13
5. CONCLUSIONES
Los algoritmos de programación dinámica hacen uso de memoria auxiliar para guardar valores pre
calculados.
ADA Página 14
6. BIBLIOGRAFIA
ADA Página 15
7. ANEXOS
1. Implementación fuerza bruta
1. import java.util.Scanner;
2.
3. public class RODCUTTINGFUERZABRUTA {
4. public RODCUTTINGFUERZABRUTA(){
5.
6. }
7. public void procesarporfuerzabruta(){
8. int longitud=0;
9. Scanner scaner=new Scanner(System.in);
10. System.out.println("ingresa la longitud: " );
11. longitud=scaner.nextInt();
12. int precio[]=new int[longitud+1];
13. precio[0]=0;
14. for(int i=1;i<=longitud;++i){
15. System.out.println("ingresa el precio de corte para longitud: "+i+" :" );
16. precio[i]=scaner.nextInt();
17.
18. }
19. System.out.println("la ganancia es : "+rdfuerzabruta( precio,longitud));
20. }
21. public int rdfuerzabruta(int precio[],int l){
22. if(l==0)return 0;
23. int q=0;
24. for(int i=1;i<=l;++i){
25. int x=precio[i]+rdfuerzabruta(precio,l-i);
26. if(x>q)q=x;
27. }
28. return q;
29. }
30. public static void main(String[]args){
31. RODCUTTINGFUERZABRUTA test= new RODCUTTINGFUERZABRUTA();
32. test.procesarporfuerzabruta();
33. }
34. }
1. import java.util.Scanner;
2.
3. public class RODCUTTINGtopdown {
4. public RODCUTTINGtopdown(){}
5.
6. public int rodcuttingtopdown(int precio[],int longitud){
7. if(longitud==0)return 0;
8. int ganancia[]=new int[longitud+1];
9. for(int i=0;i<ganancia.length;++i){
10. ganancia[i]=-1;
11. }
12. return rodcuttingtopdown( ganancia,precio, longitud);
13. }
14. public int rodcuttingtopdown(int ganancia[],int precio[],int longitud){
15. if(ganancia[longitud]>=0)return ganancia[longitud];
16. if(longitud==0)return 0;
ADA Página 16
17. int q=0;
18. for(int i=1;i<=longitud;++i){
19. int x=precio[i]+rodcuttingtopdown(ganancia, precio,longitud-i);
20. if(x>q)q=x;
21. }
22. return q;
23. }
24. public void procesarportopdown(){
25. int longitud=0;
26. Scanner scaner=new Scanner(System.in);
27. System.out.println("ingresa la longitud: " );
28. longitud=scaner.nextInt();
29. int precio[]=new int[longitud+1];
30. precio[0]=0;
31. for(int i=1;i<=longitud;++i){
32. System.out.println("ingresa el precio de corte para longitud: "+i+" :" );
33. precio[i]=scaner.nextInt();
34.
35. }
36. System.out.println("la ganancia es : "+rodcuttingtopdown( precio,longitud));
37. }
38. public static void main(String[]args){
39. RODCUTTINGtopdown test= new RODCUTTINGtopdown();
40. test.procesarportopdown();
41. }
42. }
1. import java.util.Scanner;
2.
3. public class RODCUTTINGbottomup {
4. public int longitud;
5. public int costo[];
6. public int resultado[];
7. public int f[];
8. public RODCUTTINGbottomup(int n){
9. longitud=n;
10. costo =new int[n+1];
11. resultado =new int[n+1];
12. f=new int[n+1];
13. }
14. public void llena(){
15. Scanner s=new Scanner(System.in);
16. costo[0]=0;
17. for(int i=1;i<costo.length;++i){
18.
19.
20. System.out.println("ingrese costo para el tronco de longitud:"+ i+" :");
21. costo[i]=s.nextInt();
22. }
23.
24.
25. }
26. public int calcula(){
27. int n=longitud;
28. f[0]=0;
ADA Página 17
29.
30. for(int i=1;i<=n;++i){
31. f[i]=-1;
32. for(int j=1;j<=i;++j){
33. int c=costo[j]+f[i-j];
34. if(c>f[i]){
35. f[i]=c;
36. resultado[i]=j;
37.
38. }
39. }
40.
41. }
42. return f[longitud];
43. }
44. public void resultado(){
45. int n=longitud;
46. /* for(int j=0;j<=n;++j)
47. System.out.println(f[j]);
48. System.out.println("matriz resultado");
49. for(int v=0;v<=n;++v)
50. System.out.println(resultado[v]);*/
51. while(n>0){
52. System.out.println("en la fase: "+n+" se corto una longitud de "+resultado[n] );
53. n-=resultado[n];
54.
55. }
56. }
57.
58. public static void main(String[]args){
59. System.out.println("ingrese la longitud de la varilla:");
60. Scanner s=new Scanner(System.in);
61. int n=s.nextInt();
62. RODCUTTINGbottomup test=new RODCUTTINGbottomup(n);
63. test.llena();
64. int r=test.calcula();
65. System.out.println("la ganancia maxima es :"+r);
66. test.resultado();
67.
68. }
69. }
ADA Página 18