#include <iostream> #include <queue> #include <vector> using namespace std; using i64 = long long; struct Gummy { i64 color, weight, cost; }; struct TestCase { i64 n, k, m; vector<Gummy> gummies; }; TestCase read_test_case() { TestCase tc; cin >> tc.n >> tc.k >> tc.m; tc.gummies.resize(tc.n); for (auto& g : tc.gummies) { cin >> g.color >> g.weight >> g.cost; g.color--; g.weight %= tc.m; } return tc; } struct State { i64 cost, remainder; bool operator<(const State& rhs) const { return cost > rhs.cost; } }; void solve_test_case(TestCase tc); int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); solve_test_case(read_test_case()); } void solve_test_case(TestCase tc) { vector<vector<Gummy>> gummies_by_color(tc.k); for (const auto& g : tc.gummies) { gummies_by_color[g.color].push_back(g); } for (const auto& gs : gummies_by_color) { if (gs.empty()) { cout << 0 << "\n"; for (int i = 1; i < tc.m; i++) cout << -1 << "\n"; return; } } vector<i64> prev_row(tc.m, -1); vector<i64> current_row(tc.m, -1); for (int k = 0; k < tc.k; k++) { for (int r = 0; r < tc.m; r++) { for (const auto& g : gummies_by_color[k]) { if (k == 0) { if (r == g.weight) current_row[r] = current_row[r] == -1 ? g.cost : min(g.cost, current_row[r]); continue; } int prev_rem = (r - g.weight + tc.m) % tc.m; if (prev_row[prev_rem] == -1) continue; i64 res = prev_row[prev_rem] + g.cost; current_row[r] = current_row[r] == -1 ? res : min(res, current_row[r]); } } swap(prev_row, current_row); fill(current_row.begin(), current_row.end(), -1); } auto& D = prev_row; D[0] = 0; priority_queue<State> pq; vector<i64> positive; positive.reserve(tc.m); for (int i = 1; i < tc.m; i++) if (D[i] != -1) positive.push_back(i); for (auto a : positive) for (auto b : positive) { if (a > b) continue; if (D[(a + b) % tc.m] == -1 || (D[a] + D[b] < D[(a + b) % tc.m])) pq.push({D[a] + D[b], (a + b) % tc.m}); } while (!pq.empty()) { const auto [c, r] = pq.top(); pq.pop(); if (D[r] != -1 && D[r] <= c) continue; if (D[r] == -1) positive.push_back(r); D[r] = c; for (auto i : positive) if (D[(r + i) % tc.m] == -1 || (c + D[i] < D[(r + i) % tc.m])) pq.push({c + D[i], (r + i) % tc.m}); } for (auto d : D) cout << d << "\n"; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | #include <iostream> #include <queue> #include <vector> using namespace std; using i64 = long long; struct Gummy { i64 color, weight, cost; }; struct TestCase { i64 n, k, m; vector<Gummy> gummies; }; TestCase read_test_case() { TestCase tc; cin >> tc.n >> tc.k >> tc.m; tc.gummies.resize(tc.n); for (auto& g : tc.gummies) { cin >> g.color >> g.weight >> g.cost; g.color--; g.weight %= tc.m; } return tc; } struct State { i64 cost, remainder; bool operator<(const State& rhs) const { return cost > rhs.cost; } }; void solve_test_case(TestCase tc); int main() { ios_base::sync_with_stdio(false); cin.tie(nullptr); solve_test_case(read_test_case()); } void solve_test_case(TestCase tc) { vector<vector<Gummy>> gummies_by_color(tc.k); for (const auto& g : tc.gummies) { gummies_by_color[g.color].push_back(g); } for (const auto& gs : gummies_by_color) { if (gs.empty()) { cout << 0 << "\n"; for (int i = 1; i < tc.m; i++) cout << -1 << "\n"; return; } } vector<i64> prev_row(tc.m, -1); vector<i64> current_row(tc.m, -1); for (int k = 0; k < tc.k; k++) { for (int r = 0; r < tc.m; r++) { for (const auto& g : gummies_by_color[k]) { if (k == 0) { if (r == g.weight) current_row[r] = current_row[r] == -1 ? g.cost : min(g.cost, current_row[r]); continue; } int prev_rem = (r - g.weight + tc.m) % tc.m; if (prev_row[prev_rem] == -1) continue; i64 res = prev_row[prev_rem] + g.cost; current_row[r] = current_row[r] == -1 ? res : min(res, current_row[r]); } } swap(prev_row, current_row); fill(current_row.begin(), current_row.end(), -1); } auto& D = prev_row; D[0] = 0; priority_queue<State> pq; vector<i64> positive; positive.reserve(tc.m); for (int i = 1; i < tc.m; i++) if (D[i] != -1) positive.push_back(i); for (auto a : positive) for (auto b : positive) { if (a > b) continue; if (D[(a + b) % tc.m] == -1 || (D[a] + D[b] < D[(a + b) % tc.m])) pq.push({D[a] + D[b], (a + b) % tc.m}); } while (!pq.empty()) { const auto [c, r] = pq.top(); pq.pop(); if (D[r] != -1 && D[r] <= c) continue; if (D[r] == -1) positive.push_back(r); D[r] = c; for (auto i : positive) if (D[(r + i) % tc.m] == -1 || (c + D[i] < D[(r + i) % tc.m])) pq.push({c + D[i], (r + i) % tc.m}); } for (auto d : D) cout << d << "\n"; } |