#include #include #include #include #include #include #include using json = nlohmann::json; const long long W_MASS = 20000000; const long long W_VOL = 25000000; const int N_ITEMS = 12; struct Item { std::string name; int q; long long v, m, l; int original_idx; }; struct State { long long m = 0, l = 0, v = 0; std::vector counts; bool operator<(const State& other) const { if (m != other.m) return m < other.m; if (l != other.l) return l < other.l; return v > other.v; // for sorting, higher value is better } }; std::vector prune(std::vector& states) { if (states.size() <= 1) return states; std::sort(states.begin(), states.end(), [](const State& a, const State& b){ return a.v > b.v; }); std::vector final_pruned; final_pruned.reserve(states.size()); for(const auto& s : states) { bool dominated = false; for(const auto& p : final_pruned) { if (p.m <= s.m && p.l <= s.l) { // p.v >= s.v is guaranteed by sort order dominated = true; break; } } if (!dominated) { final_pruned.push_back(s); } } return final_pruned; } std::vector generate_states(const std::vector& items, int state_limit) { int n = items.size(); if (n == 0) { std::vector res; res.emplace_back(); res.back().counts.resize(0); return res; } std::vector states; states.emplace_back(); states.back().counts.resize(n, 0); for (int i = 0; i < n; ++i) { std::vector next_states; int q_eff = items[i].q; // Heuristic cap to prevent state explosion if (q_eff > 30) q_eff = 30; next_states.reserve(states.size() * (q_eff + 1)); for (const auto& s : states) { for (int c = 0; c <= q_eff; ++c) { long long next_m = s.m + c * items[i].m; long long next_l = s.l + c * items[i].l; if (next_m > W_MASS || next_l > W_VOL) { break; } State next_s; next_s.m = next_m; next_s.l = next_l; next_s.v = s.v + c * items[i].v; next_s.counts = s.counts; next_s.counts[i] = c; next_states.push_back(next_s); } } states = prune(next_states); if (states.size() > state_limit) { std::sort(states.begin(), states.end(), [](const State& a, const State& b){ return a.v > b.v; }); states.resize(state_limit); } } return states; } int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(NULL); json input_json; std::cin >> input_json; std::vector all_items; int idx_counter = 0; for (auto& [name, val] : input_json.items()) { all_items.push_back({ name, val[0].get(), val[1].get(), val[2].get(), val[3].get(), idx_counter++ }); } std::vector lumpy_items, dust_items; for (const auto& item : all_items) { if (item.q > 50 && (item.m < 100000 || item.l < 100000)) { dust_items.push_back(item); } else { lumpy_items.push_back(item); } } std::sort(dust_items.begin(), dust_items.end(), [](const Item& a, const Item& b) { double dens_a = (double)a.v / (a.m / (double)W_MASS * 0.5 + a.l / (double)W_VOL * 0.5 + 1e-9); double dens_b = (double)b.v / (b.m / (double)W_MASS * 0.5 + b.l / (double)W_VOL * 0.5 + 1e-9); return dens_a > dens_b; }); std::vector lumpy_a, lumpy_b; for (size_t i = 0; i < lumpy_items.size(); ++i) { if (i < lumpy_items.size() / 2) { lumpy_a.push_back(lumpy_items[i]); } else { lumpy_b.push_back(lumpy_items[i]); } } int state_limit = 4000; auto states_a = generate_states(lumpy_a, state_limit); auto states_b = generate_states(lumpy_b, state_limit); long long max_total_value = -1; std::vector best_counts(N_ITEMS, 0); for (const auto& s_a : states_a) { for (const auto& s_b : states_b) { long long current_m = s_a.m + s_b.m; long long current_l = s_a.l + s_b.l; if (current_m > W_MASS || current_l > W_VOL) continue; long long current_v = s_a.v + s_b.v; std::vector current_counts(N_ITEMS, 0); for (size_t i = 0; i < lumpy_a.size(); ++i) current_counts[lumpy_a[i].original_idx] = s_a.counts[i]; for (size_t i = 0; i < lumpy_b.size(); ++i) current_counts[lumpy_b[i].original_idx] = s_b.counts[i]; long long m_rem = W_MASS - current_m; long long l_rem = W_VOL - current_l; long long dust_v = 0; for (const auto& item : dust_items) { int num_to_take = item.q; if (item.m > 0) num_to_take = std::min(num_to_take, (int)(m_rem / item.m)); if (item.l > 0) num_to_take = std::min(num_to_take, (int)(l_rem / item.l)); if (num_to_take > 0) { m_rem -= (long long)num_to_take * item.m; l_rem -= (long long)num_to_take * item.l; dust_v += (long long)num_to_take * item.v; current_counts[item.original_idx] += num_to_take; } } if (current_v + dust_v > max_total_value) { max_total_value = current_v + dust_v; best_counts = current_counts; } } } // A pure greedy solution on all items as a baseline { long long m_rem = W_MASS; long long l_rem = W_VOL; long long current_v = 0; std::vector current_counts(N_ITEMS, 0); std::vector sorted_all = all_items; std::sort(sorted_all.begin(), sorted_all.end(), [](const Item& a, const Item& b) { double dens_a = (double)a.v / (a.m / (double)W_MASS * 0.5 + a.l / (double)W_VOL * 0.5 + 1e-9); double dens_b = (double)b.v / (b.m / (double)W_MASS * 0.5 + b.l / (double)W_VOL * 0.5 + 1e-9); return dens_a > dens_b; }); for (const auto& item : sorted_all) { int num_to_take = item.q; if (item.m > 0) num_to_take = std::min(num_to_take, (int)(m_rem / item.m)); if (item.l > 0) num_to_take = std::min(num_to_take, (int)(l_rem / item.l)); if (num_to_take > 0) { m_rem -= (long long)num_to_take * item.m; l_rem -= (long long)num_to_take * item.l; current_v += (long long)num_to_take * item.v; current_counts[item.original_idx] = num_to_take; } } if (current_v > max_total_value) { best_counts = current_counts; } } json output_json; for (int i = 0; i < N_ITEMS; ++i) { output_json[all_items[i].name] = best_counts[i]; } std::cout << output_json.dump(1, '\t') << std::endl; return 0; }