| #include <iostream> |
| #include <vector> |
| #include <string> |
| #include <algorithm> |
| #include <map> |
| #include <cmath> |
| #include <ctime> |
| #include <random> |
| #include <climits> |
|
|
| using namespace std; |
|
|
| |
| 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<int> counts; |
| long long total_v; |
| long long total_m; |
| long long total_l; |
| }; |
|
|
| vector<Item> items; |
| vector<string> key_order; |
| Solution best_sol; |
|
|
| |
| 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) { |
| |
| while (i < n && data[i] != '"') i++; |
| if (i >= n) break; |
| i++; |
|
|
| string key = ""; |
| while (i < n && data[i] != '"') { |
| key += data[i]; |
| i++; |
| } |
| i++; |
|
|
| |
| size_t temp_i = i; |
| while (temp_i < n && isspace(data[temp_i])) temp_i++; |
| if (temp_i >= n || data[temp_i] != ':') { |
| |
| i = temp_i; |
| continue; |
| } |
| i = temp_i + 1; |
|
|
| |
| while (i < n && data[i] != '[') i++; |
| if (i >= n) break; |
| i++; |
|
|
| |
| 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); |
|
|
| |
| 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<string, int> name_to_idx; |
| for (int i = 0; i < N; ++i) { |
| name_to_idx[items[i].name] = i; |
| } |
|
|
| |
| 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(); |
|
|
| |
| |
| while ((double)(clock() - start_time) / CLOCKS_PER_SEC < 0.4) { |
| |
| double alpha = (double)(rng() % 1001) / 1000.0; |
| vector<int> p(N); |
| for (int k = 0; k < N; ++k) p[k] = k; |
|
|
| |
| 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; |
| } |
| } |
|
|
| |
| |
| Solution curr = best_sol; |
| vector<int> candidates; |
| candidates.reserve(N); |
|
|
| int iter = 0; |
| while (true) { |
| iter++; |
| |
| 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) { |
| |
| 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; |
|
|
| |
| while (next_sol.total_m > MAX_M || next_sol.total_l > MAX_L) { |
| candidates.clear(); |
| for(int k=0; k<N; ++k) if(next_sol.counts[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 (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) { |
| |
| 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; |
| |
| |
| 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 { |
| |
| 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; |
| } |
| } |
| } |
| } |
|
|
| |
| 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; |
| } |