#include #include #include #include #include #include #include using namespace std; const long long M = 20000000; // mg const long long L = 25000000; // µL struct Treasure { string name; long long q; // max quantity long long v; // value per item long long m; // mass per item (mg) long long l; // volume per item (µL) double density; }; vector treasures; void parseInput() { string s; char c; while (cin.get(c)) s += c; size_t i = 0; auto skipWS = [&]() { while (i < s.size() && isspace(s[i])) i++; }; skipWS(); if (s[i] != '{') return; i++; while (true) { skipWS(); if (s[i] == '}') break; if (s[i] == '"') { i++; size_t start = i; while (s[i] != '"') i++; string key = s.substr(start, i - start); i++; // skip '"' skipWS(); if (s[i] != ':') return; i++; skipWS(); if (s[i] != '[') return; i++; vector nums; for (int j = 0; j < 4; j++) { skipWS(); long long num = 0; while (i < s.size() && isdigit(s[i])) { num = num * 10 + (s[i] - '0'); i++; } nums.push_back(num); if (j < 3) { skipWS(); if (s[i] != ',') return; i++; } } skipWS(); if (s[i] != ']') return; i++; treasures.push_back({key, nums[0], nums[1], nums[2], nums[3], 0.0}); skipWS(); if (s[i] == ',') i++; else if (s[i] == '}') break; else return; } } } vector greedy(const vector& order) { vector cnt(treasures.size(), 0); long long cur_m = 0, cur_l = 0; for (int idx : order) { const Treasure& t = treasures[idx]; long long maxTake = t.q; if (t.m > 0) maxTake = min(maxTake, (M - cur_m) / t.m); if (t.l > 0) maxTake = min(maxTake, (L - cur_l) / t.l); cnt[idx] = maxTake; cur_m += maxTake * t.m; cur_l += maxTake * t.l; } return cnt; } void improve(vector& cnt, long long& cur_m, long long& cur_l, long long& cur_v) { bool improved = true; while (improved) { improved = false; // try to add one item for (int i = 0; i < (int)treasures.size(); i++) { if (cnt[i] < treasures[i].q) { long long new_m = cur_m + treasures[i].m; long long new_l = cur_l + treasures[i].l; if (new_m <= M && new_l <= L) { cnt[i]++; cur_m = new_m; cur_l = new_l; cur_v += treasures[i].v; improved = true; } } } // try to swap: remove one from j, add one to i for (int i = 0; i < (int)treasures.size() && !improved; i++) { for (int j = 0; j < (int)treasures.size(); j++) { if (i == j) continue; if (cnt[i] < treasures[i].q && cnt[j] > 0) { long long delta_m = treasures[i].m - treasures[j].m; long long delta_l = treasures[i].l - treasures[j].l; long long delta_v = treasures[i].v - treasures[j].v; if (delta_v > 0 && cur_m + delta_m <= M && cur_l + delta_l <= L) { cnt[i]++; cnt[j]--; cur_m += delta_m; cur_l += delta_l; cur_v += delta_v; improved = true; break; } } } if (improved) break; } } } void finalRefine(vector& cnt, long long& cur_m, long long& cur_l, long long& cur_v) { int n = treasures.size(); for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { long long cur_xi = cnt[i], cur_xj = cnt[j]; long long base_m = cur_m - cur_xi*treasures[i].m - cur_xj*treasures[j].m; long long base_l = cur_l - cur_xi*treasures[i].l - cur_xj*treasures[j].l; long long base_v = cur_v - cur_xi*treasures[i].v - cur_xj*treasures[j].v; long long best_xi = cur_xi, best_xj = cur_xj; long long best_m = cur_m, best_l = cur_l, best_v = cur_v; for (long long xi = max(0LL, cur_xi-10); xi <= min(treasures[i].q, cur_xi+10); xi++) { for (long long xj = max(0LL, cur_xj-10); xj <= min(treasures[j].q, cur_xj+10); xj++) { long long new_m = base_m + xi*treasures[i].m + xj*treasures[j].m; long long new_l = base_l + xi*treasures[i].l + xj*treasures[j].l; if (new_m <= M && new_l <= L) { long long new_v = base_v + xi*treasures[i].v + xj*treasures[j].v; if (new_v > best_v) { best_v = new_v; best_m = new_m; best_l = new_l; best_xi = xi; best_xj = xj; } } } } if (best_xi != cur_xi || best_xj != cur_xj) { cnt[i] = best_xi; cnt[j] = best_xj; cur_m = best_m; cur_l = best_l; cur_v = best_v; } } } } int main() { parseInput(); int n = treasures.size(); // compute density: value per combined resource for (int i = 0; i < n; i++) { // density = v_i / (m_i/M + l_i/L) = v_i * M * L / (m_i * L + l_i * M) double denom = treasures[i].m * L + treasures[i].l * M; treasures[i].density = (denom > 0) ? (treasures[i].v * M * L / denom) : 1e18; } vector order(n); for (int i = 0; i < n; i++) order[i] = i; sort(order.begin(), order.end(), [&](int a, int b) { return treasures[a].density > treasures[b].density; }); // initial solution from density order vector best_cnt = greedy(order); long long best_m = 0, best_l = 0, best_v = 0; for (int i = 0; i < n; i++) { best_m += best_cnt[i] * treasures[i].m; best_l += best_cnt[i] * treasures[i].l; best_v += best_cnt[i] * treasures[i].v; } improve(best_cnt, best_m, best_l, best_v); // random permutations mt19937 rng(123456); // fixed seed for reproducibility for (int iter = 0; iter < 100; iter++) { shuffle(order.begin(), order.end(), rng); vector cnt = greedy(order); long long cur_m = 0, cur_l = 0, cur_v = 0; for (int i = 0; i < n; i++) { cur_m += cnt[i] * treasures[i].m; cur_l += cnt[i] * treasures[i].l; cur_v += cnt[i] * treasures[i].v; } improve(cnt, cur_m, cur_l, cur_v); if (cur_v > best_v) { best_v = cur_v; best_m = cur_m; best_l = cur_l; best_cnt = cnt; } } // final refinement on pairs finalRefine(best_cnt, best_m, best_l, best_v); // output JSON cout << "{\n"; for (int i = 0; i < n; i++) { cout << " \"" << treasures[i].name << "\": " << best_cnt[i]; if (i != n-1) cout << ","; cout << "\n"; } cout << "}\n"; return 0; }