#include #include #include #include #include #include #include #include #include using namespace std; // Problem constants const long long MAX_M = 20000000; const long long MAX_L = 25000000; struct Item { string name; int q; long long v, m, l; int original_index; }; struct Solution { vector counts; long long total_v; long long total_m; long long total_l; }; vector items; vector key_order; Solution best_sol; // Parse JSON from stdin void parse_input() { string data; char c; while (cin.get(c)) data += c; size_t n = data.size(); size_t i = 0; while (i < n) { // Find start of a key string while (i < n && data[i] != '"') i++; if (i >= n) break; i++; // skip " string key = ""; while (i < n && data[i] != '"') { key += data[i]; i++; } i++; // skip closing " // Search for colon to confirm it's a key size_t temp_i = i; while (temp_i < n && isspace(data[temp_i])) temp_i++; if (temp_i >= n || data[temp_i] != ':') { // Not a key-value pair we are interested in (or end of file) i = temp_i; continue; } i = temp_i + 1; // skip : // Search for array start while (i < n && data[i] != '[') i++; if (i >= n) break; i++; // skip [ // Parse 4 numbers long long vals[4]; for (int k = 0; k < 4; ++k) { while (i < n && !isdigit(data[i])) i++; string num_s = ""; while (i < n && isdigit(data[i])) { num_s += data[i]; i++; } if (!num_s.empty()) vals[k] = stoll(num_s); else vals[k] = 0; } Item item; item.name = key; item.q = (int)vals[0]; item.v = vals[1]; item.m = vals[2]; item.l = vals[3]; item.original_index = items.size(); items.push_back(item); key_order.push_back(key); // skip until ] while (i < n && data[i] != ']') i++; i++; } } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); parse_input(); int N = items.size(); if (N == 0) { cout << "{}" << endl; return 0; } // Map name to index for easy lookup later map name_to_idx; for (int i = 0; i < N; ++i) { name_to_idx[items[i].name] = i; } // Initialize best solution best_sol.counts.assign(N, 0); best_sol.total_v = 0; best_sol.total_m = 0; best_sol.total_l = 0; mt19937 rng(12345); clock_t start_time = clock(); // Phase 1: GRASP (Greedy Randomized Adaptive Search Procedure) // Run for 40% of allowed time while ((double)(clock() - start_time) / CLOCKS_PER_SEC < 0.4) { // Random alpha for linear combination of constraints double alpha = (double)(rng() % 1001) / 1000.0; vector p(N); for (int k = 0; k < N; ++k) p[k] = k; // Randomized sorting based on value density shuffle(p.begin(), p.end(), rng); sort(p.begin(), p.end(), [&](int a, int b) { double m_norm_a = (double)items[a].m / MAX_M; double l_norm_a = (double)items[a].l / MAX_L; double cost_a = alpha * m_norm_a + (1.0 - alpha) * l_norm_a; double m_norm_b = (double)items[b].m / MAX_M; double l_norm_b = (double)items[b].l / MAX_L; double cost_b = alpha * m_norm_b + (1.0 - alpha) * l_norm_b; if (cost_a <= 1e-12) return true; if (cost_b <= 1e-12) return false; double score_a = items[a].v / cost_a; double score_b = items[b].v / cost_b; return score_a > score_b; }); Solution curr; curr.counts.assign(N, 0); curr.total_v = 0; curr.total_m = 0; curr.total_l = 0; for (int idx : p) { long long rem_m = MAX_M - curr.total_m; long long rem_l = MAX_L - curr.total_l; int can_take = items[idx].q; if (items[idx].m > 0) can_take = min((long long)can_take, rem_m / items[idx].m); if (items[idx].l > 0) can_take = min((long long)can_take, rem_l / items[idx].l); if (can_take > 0) { curr.counts[idx] = can_take; curr.total_v += (long long)can_take * items[idx].v; curr.total_m += (long long)can_take * items[idx].m; curr.total_l += (long long)can_take * items[idx].l; } } if (curr.total_v > best_sol.total_v) { best_sol = curr; } } // Phase 2: Local Search / Hill Climbing // Start from best found in GRASP Solution curr = best_sol; vector candidates; candidates.reserve(N); int iter = 0; while (true) { iter++; // Check time every 1024 iterations if ((iter & 1023) == 0) { if ((double)(clock() - start_time) / CLOCKS_PER_SEC > 0.98) break; } Solution next_sol = curr; int move_type = rng() % 3; if (move_type == 0) { // Move: Add item and Repair if needed int idx = rng() % N; if (next_sol.counts[idx] < items[idx].q) { next_sol.counts[idx]++; next_sol.total_v += items[idx].v; next_sol.total_m += items[idx].m; next_sol.total_l += items[idx].l; // Repair if invalid while (next_sol.total_m > MAX_M || next_sol.total_l > MAX_L) { candidates.clear(); for(int k=0; k 0) candidates.push_back(k); if(candidates.empty()) break; int victim = candidates[rng() % candidates.size()]; next_sol.counts[victim]--; next_sol.total_v -= items[victim].v; next_sol.total_m -= items[victim].m; next_sol.total_l -= items[victim].l; } // If valid and not worse, accept if (next_sol.total_m <= MAX_M && next_sol.total_l <= MAX_L) { if (next_sol.total_v >= curr.total_v) { curr = next_sol; if (curr.total_v > best_sol.total_v) best_sol = curr; } } } } else if (move_type == 1) { // Move: Swap (Add i, Remove j) int i = rng() % N; int j = rng() % N; if (i != j && next_sol.counts[i] < items[i].q && next_sol.counts[j] > 0) { next_sol.counts[i]++; next_sol.total_v += items[i].v; next_sol.total_m += items[i].m; next_sol.total_l += items[i].l; next_sol.counts[j]--; next_sol.total_v -= items[j].v; next_sol.total_m -= items[j].m; next_sol.total_l -= items[j].l; // Only accept if valid and not worse if (next_sol.total_m <= MAX_M && next_sol.total_l <= MAX_L) { if (next_sol.total_v >= curr.total_v) { curr = next_sol; if (curr.total_v > best_sol.total_v) best_sol = curr; } } } } else { // Move: Fill slack (Add only, valid check immediately) int idx = rng() % N; if (next_sol.counts[idx] < items[idx].q) { if (next_sol.total_m + items[idx].m <= MAX_M && next_sol.total_l + items[idx].l <= MAX_L) { next_sol.counts[idx]++; next_sol.total_v += items[idx].v; next_sol.total_m += items[idx].m; next_sol.total_l += items[idx].l; curr = next_sol; if (curr.total_v > best_sol.total_v) best_sol = curr; } } } } // Output JSON cout << "{" << endl; for (size_t i = 0; i < key_order.size(); ++i) { string key = key_order[i]; int idx = name_to_idx[key]; cout << " \"" << key << "\": " << best_sol.counts[idx]; if (i < key_order.size() - 1) cout << ","; cout << endl; } cout << "}" << endl; return 0; }