Cloud Computing
Puede tentarnos al principio hacer una DP bidimensional con la cantidad de compras de computadoras y la cantidad de pedidos de clientes, pero eso daría una transición fea e ineficiente.
En su lugar, agrupemos ambas cosas en un único arreglo de “transacciones”. Cada transacción tiene tres atributos: el cambio en la cantidad de núcleos, la frecuencia de reloj asociada de los núcleos y el cambio en las ganancias totales. Por ejemplo, el caso de ejemplo tendría un arreglo de transacciones que se ve así:
| Cambio de núcleos | Frecuencia de reloj | Cambio de ganancia |
| 4 | 2200 | -700 |
| 2 | 1800 | -10 |
| 20 | 2550 | -9999 |
| 4 | 2000 | -750 |
| -1 | 1500 | 300 |
| -6 | 1900 | 1500 |
| -3 | 2400 | 4550 |
Ahora ordenamos el arreglo por frecuencia de reloj en orden inverso, lo que da esto:
| Cambio de núcleos | Frecuencia de reloj | Cambio de ganancia |
| 20 | 2550 | -9999 |
| -3 | 2400 | 4550 |
| 4 | 2200 | -700 |
| 4 | 2000 | -750 |
| -6 | 1900 | 1500 |
| 2 | 1800 | -10 |
| -1 | 1500 | 300 |
Nótese que en este orden, mientras un pedido de cliente venga después de una compra de computadora, la computadora podrá satisfacer el pedido siempre que haya núcleos suficientes.
Esto simplifica drásticamente el problema. Ahora podemos definir \texttt{max\\_profits}[t][c] como la ganancia máxima que podemos obtener de las primeras transacciones dado que nos quedan núcleos. Con esto, el resto del problema es una mochila (knapsack) simple.
#include <algorithm>
#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;
struct Transaction {
int cores;
int rate;
int price;
};
int main() {
vector<Transaction> poss_transactions;
int max_computers = 0;
int comp_num;
std::cin >> comp_num;
for (int c = 0; c < comp_num; c++) {
Transaction trans;
std::cin >> trans.cores >> trans.rate >> trans.price;
trans.price = -trans.price;
poss_transactions.push_back(trans);
max_computers += trans.cores;
}
int order_num;
std::cin >> order_num;
for (int o = 0; o < order_num; o++) {
Transaction trans;
std::cin >> trans.cores >> trans.rate >> trans.price;
trans.cores = -trans.cores;
poss_transactions.push_back(trans);
}
/*
* if we sort like this, then the entire clock rate issue
* goes away as long as we process them in order
*/
std::sort(poss_transactions.begin(), poss_transactions.end(),
[](const Transaction &a, const Transaction &b) -> bool {
return a.rate != b.rate ? a.rate > b.rate : a.price < b.price;
});
/*
* max_profits[t][c] = the maximum profit we can gain from the first
* t transactions given that we have c cores left
*/
vector<long long> max_profits(max_computers + 1, INT64_MIN);
max_profits[0] = 0;
for (const Transaction &t : poss_transactions) {
vector<long long> new_max(max_profits);
for (int c = 0; c <= max_computers; c++) {
int prev_comp = c - t.cores;
if (0 <= prev_comp && prev_comp <= max_computers &&
max_profits[prev_comp] != INT64_MIN) {
new_max[c] = std::max(new_max[c], max_profits[prev_comp] + t.price);
}
}
max_profits = new_max;
}
cout << *std::max_element(max_profits.begin(), max_profits.end()) << endl;
}