| #include <iostream> |
| #include <vector> |
| #include <string> |
| #include <algorithm> |
| #include <map> |
| #include <ctime> |
| #include <cstdlib> |
|
|
| using namespace std; |
|
|
| |
| struct Item { |
| string name; |
| int id; |
| long long q; |
| long long v; |
| long long m; |
| long long l; |
| }; |
|
|
| |
| const long long MAX_M = 20000000; |
| const long long MAX_L = 25000000; |
|
|
| |
| struct Solution { |
| vector<int> counts; |
| long long total_v; |
| long long total_m; |
| long long total_l; |
|
|
| Solution(int n) : counts(n, 0), total_v(0), total_m(0), total_l(0) {} |
| }; |
|
|
| vector<Item> items; |
| int N; |
|
|
| |
| void parseInput() { |
| string input, line; |
| |
| while (getline(cin, line)) { |
| input += line + " "; |
| } |
|
|
| vector<string> tokens; |
| string current; |
| bool inQuotes = false; |
| for (char c : input) { |
| if (inQuotes) { |
| if (c == '"') { |
| inQuotes = false; |
| if (!current.empty()) tokens.push_back(current); |
| current = ""; |
| } else { |
| current += c; |
| } |
| } else { |
| if (c == '"') { |
| inQuotes = true; |
| } else if (isdigit(c) || c == '-') { |
| current += c; |
| } else { |
| if (!current.empty()) { |
| tokens.push_back(current); |
| current = ""; |
| } |
| } |
| } |
| } |
| if (!current.empty()) tokens.push_back(current); |
|
|
| |
| for (size_t i = 0; i < tokens.size(); i += 5) { |
| if (i + 4 >= tokens.size()) break; |
| Item item; |
| item.name = tokens[i]; |
| item.id = (int)items.size(); |
| item.q = stoll(tokens[i+1]); |
| item.v = stoll(tokens[i+2]); |
| item.m = stoll(tokens[i+3]); |
| item.l = stoll(tokens[i+4]); |
| items.push_back(item); |
| } |
| N = (int)items.size(); |
| } |
|
|
| |
| void fillGreedy(Solution& sol, const vector<int>& order) { |
| for (int idx : order) { |
| if (sol.counts[idx] >= items[idx].q) continue; |
| |
| long long rem_m = MAX_M - sol.total_m; |
| long long rem_l = MAX_L - sol.total_l; |
| |
| if (rem_m < items[idx].m || rem_l < items[idx].l) continue; |
| |
| long long take_m = rem_m / items[idx].m; |
| long long take_l = rem_l / items[idx].l; |
| long long take_q = items[idx].q - sol.counts[idx]; |
| |
| long long count = min({take_m, take_l, take_q}); |
| |
| if (count > 0) { |
| sol.counts[idx] += count; |
| sol.total_v += count * items[idx].v; |
| sol.total_m += count * items[idx].m; |
| sol.total_l += count * items[idx].l; |
| } |
| } |
| } |
|
|
| int main() { |
| ios_base::sync_with_stdio(false); |
| cin.tie(NULL); |
| srand((unsigned)time(NULL)); |
|
|
| parseInput(); |
| |
| if (N == 0) { |
| cout << "{}" << endl; |
| return 0; |
| } |
|
|
| double start_time = (double)clock() / CLOCKS_PER_SEC; |
| |
| Solution bestSol(N); |
| |
| int iterations = 0; |
| |
| while (true) { |
| iterations++; |
| |
| if (iterations % 50 == 0) { |
| double curr_time = (double)clock() / CLOCKS_PER_SEC; |
| if (curr_time - start_time > 0.95) break; |
| } |
|
|
| |
| double alpha = (double)rand() / RAND_MAX; |
| |
| |
| if (iterations == 1) alpha = 0.0; |
| else if (iterations == 2) alpha = 1.0; |
| else if (iterations == 3) alpha = 0.5; |
|
|
| |
| vector<pair<double, int>> density(N); |
| for (int i = 0; i < N; ++i) { |
| |
| double w_m = (double)items[i].m / MAX_M; |
| double w_l = (double)items[i].l / MAX_L; |
| double cost = alpha * w_m + (1.0 - alpha) * w_l; |
| if (cost < 1e-15) cost = 1e-15; |
| density[i] = { (double)items[i].v / cost, i }; |
| } |
| |
| |
| sort(density.rbegin(), density.rend()); |
| |
| vector<int> order; |
| for(auto p : density) order.push_back(p.second); |
| |
| |
| Solution currSol(N); |
| fillGreedy(currSol, order); |
| |
| |
| |
| bool improved = true; |
| while (improved) { |
| improved = false; |
| Solution localBest = currSol; |
| |
| for (int i = 0; i < N; ++i) { |
| if (currSol.counts[i] > 0) { |
| Solution temp = currSol; |
| |
| temp.counts[i]--; |
| temp.total_v -= items[i].v; |
| temp.total_m -= items[i].m; |
| temp.total_l -= items[i].l; |
| |
| |
| fillGreedy(temp, order); |
| |
| if (temp.total_v > localBest.total_v) { |
| localBest = temp; |
| improved = true; |
| } |
| } |
| } |
| if (improved) currSol = localBest; |
| } |
|
|
| if (currSol.total_v > bestSol.total_v) { |
| bestSol = currSol; |
| } |
| } |
| |
| |
| cout << "{"; |
| map<string, int> outMap; |
| for(int i=0; i<N; ++i) { |
| outMap[items[i].name] = bestSol.counts[i]; |
| } |
| |
| bool first = true; |
| for (auto const& [key, val] : outMap) { |
| if (!first) cout << ","; |
| cout << "\n \"" << key << "\": " << val; |
| first = false; |
| } |
| cout << "\n}" << endl; |
|
|
| return 0; |
| } |