Stick Divisions
Solución en video
Por Abhiraj Mallangi
Nota: la solución en video puede no coincidir con las demás soluciones. Código en Java.
Video de YouTube (-v1Kn629m3E)
Solución
Explicación
En este problema nos piden hallar el costo mínimo para dividir un palo de longitud en palos de longitudes dadas. Ayuda pensar al revés: ¿qué pasa si partimos de palos de longitudes y los fusionamos en uno?
Resulta que esto se puede resolver usando Huffman Coding (véase también Wikipedia ). El algoritmo es simple: tomar los dos palos más cortos, fusionarlos en uno y repetir.
Si te preguntas por qué Huffman Coding siempre produce una solución óptima, véase aquí .
Como queremos seleccionar los dos palos más cortos y luego insertar el palo combinado nuevo, necesitamos una estructura de datos en la que podamos obtener el valor más pequeño de la colección, quitarlo y añadir valores nuevos. Las operaciones de inserción y eliminación se pueden hacer fácilmente con una cola de prioridad en , mientras que recuperar el valor más pequeño toma tiempo constante.
Implementación
Complejidad temporal:
#include <iostream>
#include <queue>
using namespace std;
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int x, n;
cin >> x >> n;
priority_queue<int, vector<int>, greater<int>> PQ;
for (int i = 0; i < n; i++) {
int a;
cin >> a;
PQ.push(a);
}
long long ans = 0;
for (int i = 1; i < n; i++) {
int a = PQ.top();
PQ.pop();
int b = PQ.top();
PQ.pop();
PQ.push(a + b);
ans += a + b;
}
cout << ans << "\n";
return 0;
}import java.io.*;
import java.util.*;
public class StickDivision {
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(in.readLine());
// with our algorithm the variable x will not be used at all
int x = Integer.parseInt(st.nextToken());
int n = Integer.parseInt(st.nextToken());
Queue<Integer> sticks = new PriorityQueue<Integer>();
st = new StringTokenizer(in.readLine());
for (int i = 0; i < n; i++) sticks.add(Integer.valueOf(st.nextToken()));
long costs = 0;
// we keep combining two smallest sticks a and b
// until there is only one stick remaining, which will have the length x
while (sticks.size() > 1) {
int a = sticks.remove();
int b = sticks.remove();
sticks.add(a + b);
// the length of the combined stick is the cost for dividing them
// into the separated sticks a and b
costs += a + b;
}
System.out.println(costs);
}
}import heapq
x, n = map(int, input().split())
d = list(map(int, input().split()))
heapq.heapify(d)
res = 0
for _ in range(n - 1):
a = heapq.heappop(d)
b = heapq.heappop(d)
res += a + b
heapq.heappush(d, a + b)
print(res)