Ver Mensaje Individual
  #7 (permalink)  
Antiguo 08/04/2015, 06:27
Avatar de marlanga
marlanga
 
Fecha de Ingreso: enero-2011
Ubicación: Murcia
Mensajes: 1.024
Antigüedad: 13 años, 3 meses
Puntos: 206
Respuesta: Programa para equipos

Backtracking puro, sobre un algoritmo óptimo de selección general (cualquier número de equipos, cualquier diferencia máxima de tamaño de equipo).

Se puede mejorar mucho, haciendo ramificación y poda. Pero como las operaciones que realiza son sencillas, para 20 elementos no tiene demasiado coste de tiempo (2 segundos, por lo menos en una cpu i5).
A partir de ahí empieza a dispararse el tiempo, por lo que para meter mas elementos se estaría obligado a podar.

http://jsfiddle.net/marlanga/1aqzp30q/

Código Javascript:
Ver original
  1. Array.prototype.sum = function() {
  2.     return this.length ? this.reduce(
  3.         function(a, b) {
  4.             return a + b;
  5.         }
  6.     ) : 0;
  7. }
  8.  
  9. function Equipo(){
  10.     this.miembros = [];
  11. }
  12.  
  13. Equipo.prototype.pop = function() {
  14.     return this.miembros.pop();
  15. }
  16.  
  17. Equipo.prototype.push = function(miembro) {
  18.     this.miembros.push(miembro);
  19. }
  20.  
  21. Equipo.prototype.sumar = function() {
  22.     return this.miembros.sum();
  23. }
  24.  
  25. Equipo.prototype.length = function() {
  26.     return this.miembros.length;
  27. }
  28.  
  29. Equipo.prototype.clonar = function() {
  30.     var clon = new Equipo();
  31.     for (var i = 0, n = this.miembros.length; i < n; i++) {
  32.         clon.push(this.miembros[i]);
  33.     }
  34.     return clon;
  35. }
  36.  
  37. function RyP(disponibles, numero_equipos, cantidad_miembros_diferencia) {
  38.     this.disponibles = disponibles;
  39.     this.equipos=[];
  40.     this.nEquipos = numero_equipos;
  41.     this.cantidad_miembros_diferencia = cantidad_miembros_diferencia;
  42.  
  43.     this.mejor_solucion = {
  44.         diferencia : Infinity,
  45.         equipos : null
  46.     };
  47.  
  48.     this.crearEquipos();
  49. }
  50.  
  51. RyP.prototype.crearEquipos = function() {
  52.     for(var i = 0; i < this.nEquipos; i++) {
  53.         this.equipos.push(new Equipo());
  54.     }
  55. }
  56.  
  57. RyP.prototype.exec = function() {
  58.     if (this.disponibles.length === 0) {
  59.         this.comparaSolucion();
  60.     } else {
  61.         var miembro = this.disponibles.pop();
  62.         for(var i = 0; i < this.nEquipos; i++) {
  63.             this.equipos[i].push(miembro);
  64.             this.exec();
  65.             this.equipos[i].pop();
  66.         }
  67.         this.disponibles.push(miembro);
  68.     }
  69. }
  70.  
  71. RyP.prototype.comparaSolucion = function() {
  72.     if (this.maximaDiferenciaCantidadMiembros() > this.cantidad_miembros_diferencia) return;
  73.     var diff = this.maximaDiferenciaPesoEquipo();
  74.     if (diff >= this.mejor_solucion.diferencia) return;
  75.  
  76.     this.mejor_solucion.diferencia = diff;
  77.     var clon_equipos = [];
  78.     for(var i = 0; i < this.nEquipos; i++) {
  79.         clon_equipos.push(this.equipos[i].clonar());
  80.     }
  81.     this.mejor_solucion.equipos = clon_equipos;
  82. }
  83.  
  84. RyP.prototype.maximaDiferenciaCantidadMiembros = function() {
  85.     return this.maximaDiferencia();
  86. }
  87.  
  88. RyP.prototype.maximaDiferenciaPesoEquipo = function() {
  89.     return this.maximaDiferencia(true);
  90. }
  91.  
  92. RyP.prototype.maximaDiferencia = function(condicion) {
  93.     var menor = condicion ? this.equipos[0].sumar() : this.equipos[0].length();
  94.     var mayor = menor;
  95.  
  96.     for(var i = 1; i < this.nEquipos; i++) {
  97.         var length = condicion ? this.equipos[i].sumar() :  this.equipos[i].length();
  98.         menor = Math.min(length, menor);
  99.         mayor = Math.max(length, mayor);
  100.     }
  101.  
  102.     return Math.abs(mayor - menor);
  103. }
  104.  
  105.  
  106.  
  107. var miembros = [51,49,35,32,31];
  108. var numero_equipos = 2;
  109. var diferencia_maxima_cantidad_miembros_por_equipo = 1;
  110. var resolvedor = new RyP(miembros,numero_equipos, diferencia_maxima_cantidad_miembros_por_equipo);
  111. resolvedor.exec();
  112. console.log(resolvedor.mejor_solucion);

Última edición por marlanga; 08/04/2015 a las 06:34