Name: Anonymous 2010-08-04 6:52
package AA;
import java.util.*;
/**
* El juego de la cuerda
*
* Pese a que lo más sencillo sería utilizar programación dinámica recursiva,
* cogiendo un peso o descartandolo para cada combinación (y al llegar a la
* mitad del número de personas terminar) de manera similar a como se hacía con
* el problema de la mochíla o de la balanza, el programa no entra en tiempo.
* Esto es así porque todos los elementos de la entrada SÍ son válidos para la
* solución, esto es, se trata de una minimización de DISTRIBUCIÓN de pesos.
* Cuando hay distribución, hay que utilizar ramificación y poda, de lo
* contrario el problema no entra en tiempo.
*
* @author makore
*
*/
public class P07 {
public class Nodo implements Comparable<Nodo>, Cloneable {
public int nivel;
public int pesoLadoIzqCuerda;
public int pesoLadoDchCuerda;
public int personasEscogidas;
public Nodo(int nivel, int pesoLadoIzqCuerda, int pesoLadoDchCuerda, int personasEscogidas) {
this.nivel = nivel;
this.pesoLadoIzqCuerda = pesoLadoIzqCuerda;
this.pesoLadoDchCuerda = pesoLadoDchCuerda;
this.personasEscogidas = personasEscogidas;
}
@Override
public int compareTo(Nodo arg0) {
int hc1 = this.hashCode();
int hc2 = arg0.hashCode();
if (hc1 > hc2) {
return 1;
} else if (hc1 < hc2) {
return -1;
} else {
return 0;
}
}
@Override
protected Object clone() {
return new Nodo(nivel, pesoLadoIzqCuerda, pesoLadoDchCuerda, personasEscogidas);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + nivel;
result = prime * result + personasEscogidas;
result = prime * result + pesoLadoDchCuerda;
result = prime * result + pesoLadoIzqCuerda;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Nodo))
return false;
Nodo other = (Nodo) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (nivel != other.nivel)
return false;
if (personasEscogidas != other.personasEscogidas)
return false;
if (pesoLadoDchCuerda != other.pesoLadoDchCuerda)
return false;
if (pesoLadoIzqCuerda != other.pesoLadoIzqCuerda)
return false;
return true;
}
private P07 getOuterType() {
return P07.this;
}
}
private int N; // Numero de personas
private Integer[] pesos; // Pesos de las personas
private TreeMap<Nodo, Boolean> almacen;
private int mejorResultado;
public int llamadas;
public P07() {
llamadas = 0;
mejorResultado = Integer.MAX_VALUE;
almacen = new TreeMap<Nodo, Boolean>();
}
private boolean init(String data) {
try {
String[] arr = data.split("\\p{Space}+");
N = arr.length;
pesos = new Integer[N];
for (int i = 0; i < N; i++) {
pesos[i] = Integer.parseInt(arr[i]);
}
Comparator<Integer> comparator = Collections.reverseOrder();
Arrays.sort(pesos, comparator);
mejorResultado = voraz();
} catch (Exception e) {
return false;
}
return true;
}
private int voraz() {
int[] equipo = { 0, 0 };
for (int i = 0; i < pesos.length; i++) {
equipo[i % 2] += pesos[i];
}
return Math.abs(equipo[0] - equipo[1]);
}
private void best(Nodo nodo) {
llamadas++;
int limite = N / 2;
if (almacen.containsKey(nodo) == false) {
int diferencia = Math.abs(nodo.pesoLadoDchCuerda - nodo.pesoLadoIzqCuerda);
// Caso base
if (nodo.personasEscogidas == limite) {
if (diferencia < mejorResultado) {
mejorResultado = diferencia;
}
} else if (nodo.nivel < N) {
// Poda
for (int i = nodo.nivel; i < pesos.length; i++) {
diferencia -= pesos[i];
}
if (diferencia < mejorResultado) {
// Caso recursivo
Nodo nodo1 = (Nodo) nodo.clone();
Nodo nodo2 = (Nodo) nodo.clone();
nodo1.nivel++;
nodo1.personasEscogidas++;
nodo1.pesoLadoIzqCuerda -= pesos[nodo.nivel];
nodo1.pesoLadoDchCuerda += pesos[nodo.nivel];
nodo2.nivel++;
best(nodo1);
best(nodo2);
}
}
almacen.put(nodo, true);
}
}
public int best(String data) {
if (init(data) == true) {
int sumaPesos = 0;
for (int i = 0; i < pesos.length; i++) {
sumaPesos += pesos[i];
}
Nodo nodo = new Nodo(0, sumaPesos, 0, 0);
best(nodo);
}
return mejorResultado;
}
public static void main(String[] args) {
P07 p = new P07();
String data = "25 25 1 2 45 23 65 78 23";
//String data2 = "55 70 66 65 88";
System.out.println(p.best(data));
System.out.println(p.llamadas);
}
}
import java.util.*;
/**
* El juego de la cuerda
*
* Pese a que lo más sencillo sería utilizar programación dinámica recursiva,
* cogiendo un peso o descartandolo para cada combinación (y al llegar a la
* mitad del número de personas terminar) de manera similar a como se hacía con
* el problema de la mochíla o de la balanza, el programa no entra en tiempo.
* Esto es así porque todos los elementos de la entrada SÍ son válidos para la
* solución, esto es, se trata de una minimización de DISTRIBUCIÓN de pesos.
* Cuando hay distribución, hay que utilizar ramificación y poda, de lo
* contrario el problema no entra en tiempo.
*
* @author makore
*
*/
public class P07 {
public class Nodo implements Comparable<Nodo>, Cloneable {
public int nivel;
public int pesoLadoIzqCuerda;
public int pesoLadoDchCuerda;
public int personasEscogidas;
public Nodo(int nivel, int pesoLadoIzqCuerda, int pesoLadoDchCuerda, int personasEscogidas) {
this.nivel = nivel;
this.pesoLadoIzqCuerda = pesoLadoIzqCuerda;
this.pesoLadoDchCuerda = pesoLadoDchCuerda;
this.personasEscogidas = personasEscogidas;
}
@Override
public int compareTo(Nodo arg0) {
int hc1 = this.hashCode();
int hc2 = arg0.hashCode();
if (hc1 > hc2) {
return 1;
} else if (hc1 < hc2) {
return -1;
} else {
return 0;
}
}
@Override
protected Object clone() {
return new Nodo(nivel, pesoLadoIzqCuerda, pesoLadoDchCuerda, personasEscogidas);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + getOuterType().hashCode();
result = prime * result + nivel;
result = prime * result + personasEscogidas;
result = prime * result + pesoLadoDchCuerda;
result = prime * result + pesoLadoIzqCuerda;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Nodo))
return false;
Nodo other = (Nodo) obj;
if (!getOuterType().equals(other.getOuterType()))
return false;
if (nivel != other.nivel)
return false;
if (personasEscogidas != other.personasEscogidas)
return false;
if (pesoLadoDchCuerda != other.pesoLadoDchCuerda)
return false;
if (pesoLadoIzqCuerda != other.pesoLadoIzqCuerda)
return false;
return true;
}
private P07 getOuterType() {
return P07.this;
}
}
private int N; // Numero de personas
private Integer[] pesos; // Pesos de las personas
private TreeMap<Nodo, Boolean> almacen;
private int mejorResultado;
public int llamadas;
public P07() {
llamadas = 0;
mejorResultado = Integer.MAX_VALUE;
almacen = new TreeMap<Nodo, Boolean>();
}
private boolean init(String data) {
try {
String[] arr = data.split("\\p{Space}+");
N = arr.length;
pesos = new Integer[N];
for (int i = 0; i < N; i++) {
pesos[i] = Integer.parseInt(arr[i]);
}
Comparator<Integer> comparator = Collections.reverseOrder();
Arrays.sort(pesos, comparator);
mejorResultado = voraz();
} catch (Exception e) {
return false;
}
return true;
}
private int voraz() {
int[] equipo = { 0, 0 };
for (int i = 0; i < pesos.length; i++) {
equipo[i % 2] += pesos[i];
}
return Math.abs(equipo[0] - equipo[1]);
}
private void best(Nodo nodo) {
llamadas++;
int limite = N / 2;
if (almacen.containsKey(nodo) == false) {
int diferencia = Math.abs(nodo.pesoLadoDchCuerda - nodo.pesoLadoIzqCuerda);
// Caso base
if (nodo.personasEscogidas == limite) {
if (diferencia < mejorResultado) {
mejorResultado = diferencia;
}
} else if (nodo.nivel < N) {
// Poda
for (int i = nodo.nivel; i < pesos.length; i++) {
diferencia -= pesos[i];
}
if (diferencia < mejorResultado) {
// Caso recursivo
Nodo nodo1 = (Nodo) nodo.clone();
Nodo nodo2 = (Nodo) nodo.clone();
nodo1.nivel++;
nodo1.personasEscogidas++;
nodo1.pesoLadoIzqCuerda -= pesos[nodo.nivel];
nodo1.pesoLadoDchCuerda += pesos[nodo.nivel];
nodo2.nivel++;
best(nodo1);
best(nodo2);
}
}
almacen.put(nodo, true);
}
}
public int best(String data) {
if (init(data) == true) {
int sumaPesos = 0;
for (int i = 0; i < pesos.length; i++) {
sumaPesos += pesos[i];
}
Nodo nodo = new Nodo(0, sumaPesos, 0, 0);
best(nodo);
}
return mejorResultado;
}
public static void main(String[] args) {
P07 p = new P07();
String data = "25 25 1 2 45 23 65 78 23";
//String data2 = "55 70 66 65 88";
System.out.println(p.best(data));
System.out.println(p.llamadas);
}
}