UVa 410: Station Balance

João Pedro Neto

Leiam primeiro o enunciado do problema.

Em cada caixa (chamber) podemos guardar até dois valores (specimens).

Vamos ter C caixas e S valores representados por um conjunto M. O S pode variar entre 1 e 2C.

Uma forma de simplificar o problema é assumir um número constante de 2C valores, usado zeros para preencher o resto.

Por exemplo, se C = 3 e M = {3,6,8,10}, ampliamos M para ter 2*C=6 valores, ie, M = {0,0,3,6,8,10}.

A técnica gananciosa neste caso é emparelhar o menor valor com o maior valor, o 2º menor com o 2º maior, e assim sucessivamente. Isto só funciona porque estamos a guardar no máximo dois valores por caixa.

Qualquer troca de valores iria aumentar as diferenças entre caixas e assim aumentar o factor de imbalance que pretendemos ser mínimo.

Uma solução possível do problema:

public class UVa_410_StationBalance {

static double computeImbalance(int[] chambers) {

double avg = 0.0; // compute masses' average
for(int i=0; i<chambers.length; i++)

avg += chambers[i];
avg /= chambers.length;

double imbalance = 0.0; // compute imbalance = \sum_i | chamber_i - avg |
for(int i=0; i<chambers.length; i++)

imbalance += Math.abs(chambers[i] - avg);
return imbalance;
}

Este primeiro método calcula o factor de imbalance descrito no enunciado, ie, a soma dos módulos das diferenças entre cada caixa e a média de valores armazenados nas caixas.

O restante código lê os dados, e para cada problem set, calcula a partição com a solução gananciosa e imprime o relatório pedido:

   public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

int count_set = 0;
while (sc.hasNext()) {
count_set++;

// read data for each input set
int C = sc.nextInt();

int[] chambers = new int[C];
int[] masses = new int[2*C]; // already leaving the extra zeros

int S = sc.nextInt();

for(int i=0;i<S; i++)
masses[i] = sc.nextInt();

Arrays.sort(masses);

// the greedy solution
for(int i=0; i<masses.length/2; i++)

chambers[i] = masses[i] + masses[masses.length-i-1];

// print report
if (count_set>1) System.out.println();

System.out.println("Set #" + count_set);
for(int i=0; i<C; i++) {
System.out.print(" " + i + ":");
if (masses[i] != 0)
System.out.print(" " + masses[i]);
if (masses[masses.length-i-1] != 0)
System.out.print(" " + masses[masses.length-i-1]);
System.out.println();
}
System.out.println(
String.format("IMBALANCE = %1.5f", computeImbalance(chambers)));
}
        System.out.println();
sc.close();

}
}

Um último detalhe: a especificação do output do enunciado é ambigua. Não se diz exactamente qual a ordem pela qual os valores devem ser colocados nas caixas, e não há informação suficiente nos exemplos para perceber essa ordem. Deste modo, esta solução não passa no UVa. Mas isto é resultado de um enunciado mal concebido, dado que os imbalances estão a ser corretamente calculados.

Last modified: Tuesday, 9 March 2021, 2:54 PM