| #include <bits/stdc++.h> |
| using namespace std; |
|
|
| struct Item { |
| string name; |
| long long q, v, m, l; |
| }; |
|
|
| struct Solution { |
| vector<long long> x; |
| long long value; |
| long long remM, remL; |
| }; |
|
|
| static const long long CAP_M = 20LL * 1000000LL; |
| static const long long CAP_L = 25LL * 1000000LL; |
|
|
| void skipSpaces(const string& s, size_t& i){ |
| while(i < s.size() && isspace((unsigned char)s[i])) i++; |
| } |
|
|
| bool parseString(const string& s, size_t& i, string& out){ |
| skipSpaces(s, i); |
| if(i >= s.size() || s[i] != '"') return false; |
| i++; |
| string res; |
| while(i < s.size() && s[i] != '"'){ |
| |
| res.push_back(s[i]); |
| i++; |
| } |
| if(i >= s.size() || s[i] != '"') return false; |
| i++; |
| out = res; |
| return true; |
| } |
|
|
| bool parseInt(const string& s, size_t& i, long long& val){ |
| skipSpaces(s, i); |
| bool neg = false; |
| if(i < s.size() && (s[i] == '-' || s[i] == '+')){ |
| neg = (s[i]=='-'); |
| i++; |
| } |
| skipSpaces(s, i); |
| if(i >= s.size() || !isdigit((unsigned char)s[i])) return false; |
| long long v = 0; |
| while(i < s.size() && isdigit((unsigned char)s[i])){ |
| v = v*10 + (s[i]-'0'); |
| i++; |
| } |
| val = neg ? -v : v; |
| return true; |
| } |
|
|
| bool parseArray4(const string& s, size_t& i, array<long long,4>& arr){ |
| skipSpaces(s, i); |
| if(i >= s.size() || s[i] != '[') return false; |
| i++; |
| for(int k=0;k<4;k++){ |
| skipSpaces(s, i); |
| |
| long long x; |
| if(!parseInt(s, i, x)) return false; |
| arr[k]=x; |
| skipSpaces(s, i); |
| if(k<3){ |
| if(i >= s.size()) return false; |
| |
| if(s[i] == ','){ i++; } |
| } |
| } |
| skipSpaces(s, i); |
| |
| while(i < s.size() && s[i] != ']'){ |
| |
| if(s[i]==','){ i++; } |
| else if(isspace((unsigned char)s[i])) i++; |
| else break; |
| } |
| if(i >= s.size() || s[i] != ']') return false; |
| i++; |
| return true; |
| } |
|
|
| vector<Item> parseInput(const string& s){ |
| vector<Item> items; |
| size_t i=0; |
| skipSpaces(s,i); |
| if(i<s.size() && s[i]=='{') i++; |
| while(i < s.size()){ |
| skipSpaces(s,i); |
| if(i < s.size() && s[i]=='}'){ i++; break; } |
| string key; |
| if(!parseString(s,i,key)) break; |
| skipSpaces(s,i); |
| if(i >= s.size() || s[i] != ':') break; |
| i++; |
| array<long long,4> arr; |
| if(!parseArray4(s,i,arr)) break; |
| items.push_back({key, arr[0], arr[1], arr[2], arr[3]}); |
| skipSpaces(s,i); |
| if(i < s.size() && s[i]==','){ i++; continue; } |
| } |
| return items; |
| } |
|
|
| long long ceil_div(long long a, long long b){ |
| if (a <= 0) return 0; |
| return (a + b - 1) / b; |
| } |
|
|
| Solution greedyFill(const vector<Item>& items, const vector<int>& order){ |
| int n = items.size(); |
| Solution sol; |
| sol.x.assign(n,0); |
| sol.remM = CAP_M; |
| sol.remL = CAP_L; |
| sol.value = 0; |
| for(int idx : order){ |
| const auto& it = items[idx]; |
| if (it.m > CAP_M || it.l > CAP_L) continue; |
| long long byM = sol.remM / it.m; |
| long long byL = sol.remL / it.l; |
| long long take = min({it.q, byM, byL}); |
| if(take <= 0) continue; |
| sol.x[idx] += take; |
| sol.remM -= take * it.m; |
| sol.remL -= take * it.l; |
| sol.value += take * it.v; |
| } |
| return sol; |
| } |
|
|
| void tryDirectFill(const vector<Item>& items, const vector<int>& order, Solution& sol){ |
| for(int idx : order){ |
| const auto& it = items[idx]; |
| if (it.m > CAP_M || it.l > CAP_L) continue; |
| long long canq = it.q - sol.x[idx]; |
| if(canq <= 0) continue; |
| long long byM = sol.remM / it.m; |
| long long byL = sol.remL / it.l; |
| long long take = min({canq, byM, byL}); |
| if(take <= 0) continue; |
| sol.x[idx] += take; |
| sol.remM -= take * it.m; |
| sol.remL -= take * it.l; |
| sol.value += take * it.v; |
| } |
| } |
|
|
| bool improveOneSwap(const vector<Item>& items, Solution& sol){ |
| int n = items.size(); |
| |
| for(int a=0;a<n;a++){ |
| const auto& ia = items[a]; |
| if(sol.x[a] >= ia.q) continue; |
| if (ia.m > CAP_M || ia.l > CAP_L) continue; |
| long long needM = max(0LL, ia.m - sol.remM); |
| long long needL = max(0LL, ia.l - sol.remL); |
| if(needM==0 && needL==0){ |
| |
| sol.x[a] += 1; |
| sol.remM -= ia.m; |
| sol.remL -= ia.l; |
| sol.value += ia.v; |
| return true; |
| } |
| |
| for(int b=0;b<n;b++){ |
| if(sol.x[b] <= 0) continue; |
| const auto& ib = items[b]; |
| long long t = max(ceil_div(needM, ib.m), ceil_div(needL, ib.l)); |
| if(t <= 0) t = 1; |
| if(t > sol.x[b]) continue; |
| long long deltaV = ia.v - t * ib.v; |
| if(deltaV <= 0) continue; |
| |
| sol.x[a] += 1; |
| sol.x[b] -= t; |
| sol.remM = sol.remM - ia.m + t * ib.m; |
| sol.remL = sol.remL - ia.l + t * ib.l; |
| sol.value += deltaV; |
| return true; |
| } |
| } |
| return false; |
| } |
|
|
| int main(){ |
| ios::sync_with_stdio(false); |
| cin.tie(nullptr); |
| string input, line; |
| { |
| ostringstream oss; |
| oss << cin.rdbuf(); |
| input = oss.str(); |
| } |
| vector<Item> items = parseInput(input); |
| int n = items.size(); |
| if(n==0){ |
| cout << "{\n}\n"; |
| return 0; |
| } |
|
|
| |
| vector<vector<int>> strategies; |
| |
| for(int a=0;a<=10;a++){ |
| vector<pair<double,int>> score; |
| for(int i=0;i<n;i++){ |
| double wm = (double)items[i].m / (double)CAP_M; |
| double wl = (double)items[i].l / (double)CAP_L; |
| double w = a*wm + (10-a)*wl + 1e-12; |
| double s = (double)items[i].v / w; |
| score.push_back({-s, i}); |
| } |
| sort(score.begin(), score.end()); |
| vector<int> ord; |
| for(auto &p:score) ord.push_back(p.second); |
| strategies.push_back(ord); |
| } |
| |
| { |
| vector<pair<double,int>> score; |
| for(int i=0;i<n;i++){ |
| double s = (double)items[i].v / ((double)items[i].m + 1e-9); |
| score.push_back({-s, i}); |
| } |
| sort(score.begin(), score.end()); |
| vector<int> ord; |
| for(auto &p:score) ord.push_back(p.second); |
| strategies.push_back(ord); |
| } |
| |
| { |
| vector<pair<double,int>> score; |
| for(int i=0;i<n;i++){ |
| double s = (double)items[i].v / ((double)items[i].l + 1e-9); |
| score.push_back({-s, i}); |
| } |
| sort(score.begin(), score.end()); |
| vector<int> ord; |
| for(auto &p:score) ord.push_back(p.second); |
| strategies.push_back(ord); |
| } |
| |
| { |
| vector<pair<double,int>> score; |
| for(int i=0;i<n;i++){ |
| double wm = (double)items[i].m / (double)CAP_M; |
| double wl = (double)items[i].l / (double)CAP_L; |
| double w = max(wm, wl) + 1e-12; |
| double s = (double)items[i].v / w; |
| score.push_back({-s, i}); |
| } |
| sort(score.begin(), score.end()); |
| vector<int> ord; |
| for(auto &p:score) ord.push_back(p.second); |
| strategies.push_back(ord); |
| } |
|
|
| Solution best; |
| best.x.assign(n,0); |
| best.value = 0; |
| best.remM = CAP_M; |
| best.remL = CAP_L; |
|
|
| for(auto &ord : strategies){ |
| Solution sol = greedyFill(items, ord); |
| |
| |
| tryDirectFill(items, ord, sol); |
| |
| int iter=0; |
| const int MAX_ITERS = 2000; |
| while(iter < MAX_ITERS){ |
| bool improved = improveOneSwap(items, sol); |
| if(!improved) break; |
| |
| tryDirectFill(items, ord, sol); |
| iter++; |
| } |
| if(sol.value > best.value){ |
| best = sol; |
| } |
| } |
|
|
| |
| cout << "{\n"; |
| for(int i=0;i<n;i++){ |
| cout << " \"" << items[i].name << "\": " << best.x[i]; |
| if(i+1<n) cout << ",\n"; |
| else cout << "\n"; |
| } |
| cout << "}\n"; |
| return 0; |
| } |