| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| static const long long M_CAP = 20000000LL; |
| static const long long L_CAP = 25000000LL; |
|
|
| struct Item { |
| string name; |
| long long q, v, m, l; |
| int idx; |
| }; |
|
|
| struct Parser { |
| string s; |
| size_t i=0; |
| Parser(const string& str): s(str), i(0) {} |
| void skip() { |
| while (i < s.size() && (s[i]==' ' || s[i]=='\n' || s[i]=='\r' || s[i]=='\t')) i++; |
| } |
| bool peek(char c) { |
| skip(); |
| return i < s.size() && s[i]==c; |
| } |
| void expect(char c) { |
| skip(); |
| if (i>=s.size() || s[i]!=c) { |
| |
| } else { |
| i++; |
| } |
| } |
| string parseString() { |
| skip(); |
| string out; |
| if (i < s.size() && s[i]=='"') { |
| i++; |
| while (i < s.size()) { |
| char c = s[i++]; |
| if (c=='\\') { |
| if (i < s.size()) { |
| char nxt = s[i++]; |
| |
| out.push_back(nxt); |
| } |
| } else if (c=='"') { |
| break; |
| } else { |
| out.push_back(c); |
| } |
| } |
| } |
| return out; |
| } |
| long long parseNumber() { |
| skip(); |
| bool neg=false; |
| if (i<s.size() && s[i]=='-') { neg=true; i++; } |
| long long x=0; |
| while (i < s.size() && s[i]>='0' && s[i]<='9') { |
| x = x*10 + (s[i]-'0'); |
| i++; |
| } |
| return neg? -x : x; |
| } |
| }; |
|
|
| struct Solution { |
| vector<long long> cnt; |
| long long val=0; |
| long long m_used=0; |
| long long l_used=0; |
| }; |
|
|
| int main() { |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
| |
| std::string input, line; |
| { |
| std::ostringstream oss; |
| oss << cin.rdbuf(); |
| input = oss.str(); |
| } |
|
|
| |
| Parser p(input); |
| vector<Item> items; |
| p.expect('{'); |
| int idx = 0; |
| while (true) { |
| p.skip(); |
| if (p.peek('}')) { p.expect('}'); break; } |
| string key = p.parseString(); |
| p.expect(':'); |
| p.expect('['); |
| vector<long long> arr; |
| while (true) { |
| long long num = p.parseNumber(); |
| arr.push_back(num); |
| p.skip(); |
| if (p.peek(',')) { p.expect(','); p.skip(); if (p.peek(']')) { p.expect(']'); break; } } |
| else if (p.peek(']')) { p.expect(']'); break; } |
| else { |
| |
| } |
| } |
| Item it; |
| it.name = key; |
| if (arr.size() >= 4) { |
| it.q = arr[0]; |
| it.v = arr[1]; |
| it.m = arr[2]; |
| it.l = arr[3]; |
| } else { |
| it.q = 0; it.v=0; it.m=1; it.l=1; |
| } |
| it.idx = idx++; |
| items.push_back(it); |
| p.skip(); |
| if (p.peek(',')) { p.expect(','); continue; } |
| else if (p.peek('}')) { p.expect('}'); break; } |
| else { |
| |
| } |
| } |
|
|
| int n = (int)items.size(); |
| if (n == 0) { |
| cout << "{}\n"; |
| return 0; |
| } |
|
|
| |
| vector<long long> r(n, 0); |
| for (int i=0;i<n;i++) { |
| if (items[i].m > 0 && items[i].l > 0 && items[i].v > 0) { |
| long long byM = items[i].m > 0 ? (M_CAP / items[i].m) : (long long)1e18; |
| long long byL = items[i].l > 0 ? (L_CAP / items[i].l) : (long long)1e18; |
| long long rr = min(items[i].q, min(byM, byL)); |
| r[i] = max(0LL, rr); |
| } else { |
| r[i] = 0; |
| } |
| } |
|
|
| |
| vector<double> nm(n), nl(n); |
| for (int i=0;i<n;i++) { |
| nm[i] = (double)items[i].m / (double)M_CAP; |
| nl[i] = (double)items[i].l / (double)L_CAP; |
| } |
|
|
| auto now = [](){ return chrono::high_resolution_clock::now(); }; |
| auto start = now(); |
| auto elapsed_ms = [&](double limit_ms){ |
| auto t = now(); |
| double ms = chrono::duration<double, std::milli>(t - start).count(); |
| return ms; |
| }; |
|
|
| |
| struct WeightSpec { int type; double a,b; }; |
| auto greedy_build = [&](const WeightSpec& ws)->Solution { |
| vector<int> order(n); |
| iota(order.begin(), order.end(), 0); |
| vector<double> dens(n, 0.0); |
| for (int i=0;i<n;i++) { |
| if (r[i] <= 0) { dens[i] = -1e300; continue; } |
| if (ws.type == 0) { |
| double denom = ws.a * (double)items[i].m + ws.b * (double)items[i].l; |
| if (denom <= 0) denom = 1e-18; |
| dens[i] = (double)items[i].v / denom; |
| } else if (ws.type == 1) { |
| double denom = max(nm[i], nl[i]); |
| if (denom <= 0) denom = 1e-18; |
| dens[i] = (double)items[i].v / denom; |
| } else if (ws.type == 2) { |
| double denom = hypot(nm[i], nl[i]); |
| if (denom <= 0) denom = 1e-18; |
| dens[i] = (double)items[i].v / denom; |
| } else if (ws.type == 3) { |
| dens[i] = (double)items[i].v; |
| } else { |
| double denom = ws.a * (double)items[i].m + ws.b * (double)items[i].l; |
| if (denom <= 0) denom = 1e-18; |
| dens[i] = (double)items[i].v / denom; |
| } |
| } |
| stable_sort(order.begin(), order.end(), [&](int i, int j){ |
| if (dens[i] != dens[j]) return dens[i] > dens[j]; |
| if (items[i].v != items[j].v) return items[i].v > items[j].v; |
| double wi = (ws.a * (double)items[i].m + ws.b * (double)items[i].l); |
| double wj = (ws.a * (double)items[j].m + ws.b * (double)items[j].l); |
| return wi < wj; |
| }); |
|
|
| Solution sol; |
| sol.cnt.assign(n, 0); |
| long long Mm = M_CAP, Ll = L_CAP; |
| long long val = 0; |
| for (int idxi : order) { |
| if (r[idxi] <= 0) continue; |
| long long can_by_M = items[idxi].m > 0 ? (Mm / items[idxi].m) : 0; |
| long long can_by_L = items[idxi].l > 0 ? (Ll / items[idxi].l) : 0; |
| long long can = min(r[idxi], min(can_by_M, can_by_L)); |
| if (can <= 0) continue; |
| sol.cnt[idxi] += can; |
| val += can * items[idxi].v; |
| Mm -= can * items[idxi].m; |
| Ll -= can * items[idxi].l; |
| if (Mm <= 0 || Ll <= 0) break; |
| } |
| sol.val = val; |
| sol.m_used = M_CAP - Mm; |
| sol.l_used = L_CAP - Ll; |
| return sol; |
| }; |
|
|
| |
| auto improve = [&](Solution& sol, const WeightSpec& ws, double time_ms_budget){ |
| |
| vector<double> remDensity(n, 0.0); |
| for (int i=0;i<n;i++) { |
| if (ws.type == 0) { |
| double denom = ws.a * (double)items[i].m + ws.b * (double)items[i].l; |
| if (denom <= 0) denom = 1e-18; |
| remDensity[i] = (double)items[i].v / denom; |
| } else if (ws.type == 1) { |
| double denom = max(nm[i], nl[i]); |
| if (denom <= 0) denom = 1e-18; |
| remDensity[i] = (double)items[i].v / denom; |
| } else if (ws.type == 2) { |
| double denom = hypot(nm[i], nl[i]); |
| if (denom <= 0) denom = 1e-18; |
| remDensity[i] = (double)items[i].v / denom; |
| } else if (ws.type == 3) { |
| |
| double denom = (double)items[i].m / (double)M_CAP + (double)items[i].l / (double)L_CAP; |
| if (denom <= 0) denom = 1e-18; |
| remDensity[i] = (double)items[i].v / denom; |
| } else { |
| double denom = ws.a * (double)items[i].m + ws.b * (double)items[i].l; |
| if (denom <= 0) denom = 1e-18; |
| remDensity[i] = (double)items[i].v / denom; |
| } |
| } |
| vector<int> remOrder(n); |
| iota(remOrder.begin(), remOrder.end(), 0); |
| stable_sort(remOrder.begin(), remOrder.end(), [&](int i, int j){ |
| if (remDensity[i] != remDensity[j]) return remDensity[i] < remDensity[j]; |
| return items[i].v < items[j].v; |
| }); |
|
|
| vector<int> addOrder(n); |
| iota(addOrder.begin(), addOrder.end(), 0); |
| stable_sort(addOrder.begin(), addOrder.end(), [&](int i, int j){ |
| if (items[i].v != items[j].v) return items[i].v > items[j].v; |
| double di = nm[i] + nl[i]; |
| double dj = nm[j] + nl[j]; |
| return di < dj; |
| }); |
|
|
| long long Mm = M_CAP - sol.m_used; |
| long long Ll = L_CAP - sol.l_used; |
| long long curVal = sol.val; |
|
|
| auto time_ok = [&](){ |
| return elapsed_ms(0) < time_ms_budget; |
| }; |
|
|
| bool improved_any = true; |
| int outer_iters = 0; |
| while (improved_any && time_ok()) { |
| improved_any = false; |
| outer_iters++; |
| if (outer_iters > 100) break; |
| for (int j_idx = 0; j_idx < n && time_ok(); j_idx++) { |
| int j = addOrder[j_idx]; |
| if (r[j] <= 0) continue; |
| if (sol.cnt[j] >= r[j]) continue; |
| |
| if (Mm >= items[j].m && Ll >= items[j].l) { |
| long long can_by_M = items[j].m > 0 ? (Mm / items[j].m) : 0; |
| long long can_by_L = items[j].l > 0 ? (Ll / items[j].l) : 0; |
| long long quota = r[j] - sol.cnt[j]; |
| long long take = min(quota, min(can_by_M, can_by_L)); |
| if (take > 0) { |
| sol.cnt[j] += take; |
| Mm -= take * items[j].m; |
| Ll -= take * items[j].l; |
| curVal += take * items[j].v; |
| improved_any = true; |
| } |
| } |
| |
| bool changed = true; |
| int inner_added = 0; |
| while (changed && time_ok()) { |
| changed = false; |
| if (sol.cnt[j] >= r[j]) break; |
| if (Mm >= items[j].m && Ll >= items[j].l) { |
| sol.cnt[j] += 1; |
| Mm -= items[j].m; |
| Ll -= items[j].l; |
| curVal += items[j].v; |
| improved_any = true; |
| changed = true; |
| inner_added++; |
| if (inner_added > 64) break; |
| continue; |
| } |
| long long needM = (items[j].m > Mm) ? (items[j].m - Mm) : 0LL; |
| long long needL = (items[j].l > Ll) ? (items[j].l - Ll) : 0LL; |
| if (needM == 0 && needL == 0) continue; |
|
|
| long long freedM = 0, freedL = 0; |
| long long removedVal = 0; |
| vector<long long> removedCnt(n, 0); |
| for (int i_idx = 0; i_idx < n; i_idx++) { |
| int i2 = remOrder[i_idx]; |
| if (i2 == j) continue; |
| long long have = sol.cnt[i2]; |
| if (have <= 0) continue; |
| long long reqM = 0, reqL = 0; |
| if (needM > freedM) reqM = (needM - freedM + items[i2].m - 1) / items[i2].m; |
| if (needL > freedL) reqL = (needL - freedL + items[i2].l - 1) / items[i2].l; |
| long long need = max(reqM, reqL); |
| if (need <= 0) continue; |
| long long maxByValue = LLONG_MAX; |
| if (items[i2].v > 0) { |
| if (removedVal < items[j].v) { |
| long long cap = (items[j].v - 1 - removedVal) / items[i2].v; |
| if (cap < 0) cap = 0; |
| maxByValue = cap; |
| } else { |
| maxByValue = 0; |
| } |
| } |
| long long take = min(have, need); |
| take = min(take, maxByValue); |
| if (take <= 0) continue; |
| removedCnt[i2] += take; |
| freedM += take * items[i2].m; |
| freedL += take * items[i2].l; |
| removedVal += take * items[i2].v; |
| if ((Mm + freedM) >= items[j].m && (Ll + freedL) >= items[j].l) break; |
| } |
| if ((Mm + freedM) >= items[j].m && (Ll + freedL) >= items[j].l && removedVal < items[j].v) { |
| |
| for (int k=0;k<n;k++) { |
| if (removedCnt[k] > 0) { |
| sol.cnt[k] -= removedCnt[k]; |
| } |
| } |
| Mm += freedM; |
| Ll += freedL; |
| curVal -= removedVal; |
| |
| sol.cnt[j] += 1; |
| Mm -= items[j].m; |
| Ll -= items[j].l; |
| curVal += items[j].v; |
| improved_any = true; |
| changed = true; |
| inner_added++; |
| if (inner_added > 64) break; |
| } else { |
| |
| break; |
| } |
| } |
| } |
| } |
|
|
| sol.val = curVal; |
| sol.m_used = M_CAP - Mm; |
| sol.l_used = L_CAP - Ll; |
|
|
| |
| |
| vector<int> fillOrder(n); |
| iota(fillOrder.begin(), fillOrder.end(), 0); |
| vector<double> densFill(n, 0.0); |
| for (int i=0;i<n;i++) { |
| double denom = (double)items[i].m / (double)M_CAP + (double)items[i].l / (double)L_CAP; |
| if (denom <= 0) denom = 1e-18; |
| densFill[i] = (double)items[i].v / denom; |
| } |
| stable_sort(fillOrder.begin(), fillOrder.end(), [&](int a, int b){ |
| if (densFill[a] != densFill[b]) return densFill[a] > densFill[b]; |
| return items[a].v > items[b].v; |
| }); |
| long long Mm2 = M_CAP - sol.m_used; |
| long long Ll2 = L_CAP - sol.l_used; |
| for (int iidx : fillOrder) { |
| if (!time_ok()) break; |
| long long quota = r[iidx] - sol.cnt[iidx]; |
| if (quota <= 0) continue; |
| long long can_by_M = items[iidx].m > 0 ? (Mm2 / items[iidx].m) : 0; |
| long long can_by_L = items[iidx].l > 0 ? (Ll2 / items[iidx].l) : 0; |
| long long take = min(quota, min(can_by_M, can_by_L)); |
| if (take > 0) { |
| sol.cnt[iidx] += take; |
| sol.val += take * items[iidx].v; |
| Mm2 -= take * items[iidx].m; |
| Ll2 -= take * items[iidx].l; |
| } |
| } |
| sol.m_used = M_CAP - Mm2; |
| sol.l_used = L_CAP - Ll2; |
| }; |
|
|
| |
| vector<WeightSpec> weights; |
| |
| const int T1 = 10; |
| for (int k=0;k<=T1;k++) { |
| double t = (double)k / (double)T1; |
| WeightSpec ws{0, t / (double)M_CAP, (1.0 - t) / (double)L_CAP}; |
| weights.push_back(ws); |
| } |
| for (int k=0;k<=9;k++) { |
| double t = 0.05 + 0.1 * k; |
| WeightSpec ws{0, t / (double)M_CAP, (1.0 - t) / (double)L_CAP}; |
| weights.push_back(ws); |
| } |
| |
| vector<double> gammas = {0.25, 0.5, 1.0, 2.0, 4.0}; |
| for (double g : gammas) { |
| WeightSpec ws{0, 1.0/(double)M_CAP, g/(double)L_CAP}; |
| weights.push_back(ws); |
| } |
| |
| weights.push_back(WeightSpec{1, 0.0, 0.0}); |
| weights.push_back(WeightSpec{2, 0.0, 0.0}); |
| weights.push_back(WeightSpec{3, 0.0, 0.0}); |
|
|
| |
| Solution best; |
| best.cnt.assign(n, 0); |
| best.val = 0; |
| best.m_used = 0; |
| best.l_used = 0; |
|
|
| double time_budget_ms = 950.0; |
|
|
| |
| for (size_t wi = 0; wi < weights.size(); wi++) { |
| if (elapsed_ms(0) > time_budget_ms) break; |
| Solution sol = greedy_build(weights[wi]); |
| if (elapsed_ms(0) > time_budget_ms) { |
| if (sol.val > best.val) best = sol; |
| break; |
| } |
| |
| double remaining = time_budget_ms - elapsed_ms(0); |
| double alloc = max(10.0, remaining / (double)(weights.size() - wi + 1)); |
| improve(sol, weights[wi], elapsed_ms(0) + alloc); |
| if (sol.val > best.val) best = sol; |
| } |
|
|
| |
| long long total_m = 0, total_l = 0; |
| for (int i=0;i<n;i++) { |
| best.cnt[i] = min(best.cnt[i], r[i]); |
| if (best.cnt[i] < 0) best.cnt[i] = 0; |
| total_m += best.cnt[i] * items[i].m; |
| total_l += best.cnt[i] * items[i].l; |
| } |
| if (total_m > M_CAP || total_l > L_CAP) { |
| |
| vector<int> order(n); |
| iota(order.begin(), order.end(), 0); |
| vector<double> dens(n); |
| for (int i=0;i<n;i++) { |
| double denom = (double)items[i].m / (double)M_CAP + (double)items[i].l / (double)L_CAP; |
| if (denom <= 0) denom = 1e-18; |
| dens[i] = (double)items[i].v / denom; |
| } |
| stable_sort(order.begin(), order.end(), [&](int a, int b){ |
| if (dens[a] != dens[b]) return dens[a] < dens[b]; |
| return items[a].v < items[b].v; |
| }); |
| for (int idxi : order) { |
| while ((total_m > M_CAP || total_l > L_CAP) && best.cnt[idxi] > 0) { |
| best.cnt[idxi]--; |
| total_m -= items[idxi].m; |
| total_l -= items[idxi].l; |
| } |
| if (total_m <= M_CAP && total_l <= L_CAP) break; |
| } |
| } |
|
|
| |
| cout << "{\n"; |
| for (int i=0;i<n;i++) { |
| cout << " \"" << items[i].name << "\": " << best.cnt[i]; |
| if (i+1<n) cout << ",\n"; |
| else cout << "\n"; |
| } |
| cout << "}\n"; |
| return 0; |
| } |