#include <vector> #include <iostream> #include <climits> using namespace std; int main() { cin.tie(0); ios_base::sync_with_stdio(0); long long rodzaje, kolory, div; cin >> rodzaje >> kolory >> div; vector<vector<pair<long long, long long>>> Zelki(kolory); long long kolor, masa, cena; for (long long i = 0; i < rodzaje; i++) { cin >> kolor >> masa >> cena; Zelki[kolor - 1].push_back({ masa % div, cena }); } // Ponizej obliczanie wszystkich mozliwych wynikow po wzieciu 1 cukierka kazdego koloru. vector<long long> costs(div, (LLONG_MAX/10)); costs[0] = 0; for (long long i = 0; i < kolory; i++) { vector<long long> next(div, (LLONG_MAX/10)); for (long long j = 0; j < Zelki[i].size(); j++) { for (long long k = 0; k < div; k++) { if (costs[k] != (LLONG_MAX/10)) { next[(k + Zelki[i][j].first) % div] = min(next[(k + Zelki[i][j].first) % div], costs[k] + Zelki[i][j].second); } } } costs = next; } costs[0] = 0; // Sprawdzanie, jakie reszty mozna osiagnac po 1 cyklu. vector<long long> indexes; for (long long i = 0; i < div; i++) { if (costs[i] != (LLONG_MAX/10)) { indexes.push_back(i); } } // Ponizej wzorem problemu plecakowego znajduje sie nowe mozliwosci dla roznych reszt. Konczy sie gdy po pelnym cyklu brak jest nowych wynikow. while (!indexes.empty()) { vector<long long> newCosts(div, (LLONG_MAX/10)); for (auto& i : indexes) { for (long long j = 0; j < div; j++) { if (costs[j] != (LLONG_MAX/10)) { newCosts[(i + j) % div] = min(newCosts[(i + j) % div], costs[i] + costs[j]); } } } indexes.clear(); for (long long j = 0; j < div; j++) { if (newCosts[j] < costs[j]) { costs[j] = newCosts[j]; indexes.push_back(j); } } } // Wypisanie wyniku for (long long i = 0; i < div; i++) { if (costs[i] >= (LLONG_MAX/10)) { cout << -1 << '\n'; } else { cout << costs[i] << '\n'; } } return 0; }
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 | #include <vector> #include <iostream> #include <climits> using namespace std; int main() { cin.tie(0); ios_base::sync_with_stdio(0); long long rodzaje, kolory, div; cin >> rodzaje >> kolory >> div; vector<vector<pair<long long, long long>>> Zelki(kolory); long long kolor, masa, cena; for (long long i = 0; i < rodzaje; i++) { cin >> kolor >> masa >> cena; Zelki[kolor - 1].push_back({ masa % div, cena }); } // Ponizej obliczanie wszystkich mozliwych wynikow po wzieciu 1 cukierka kazdego koloru. vector<long long> costs(div, (LLONG_MAX/10)); costs[0] = 0; for (long long i = 0; i < kolory; i++) { vector<long long> next(div, (LLONG_MAX/10)); for (long long j = 0; j < Zelki[i].size(); j++) { for (long long k = 0; k < div; k++) { if (costs[k] != (LLONG_MAX/10)) { next[(k + Zelki[i][j].first) % div] = min(next[(k + Zelki[i][j].first) % div], costs[k] + Zelki[i][j].second); } } } costs = next; } costs[0] = 0; // Sprawdzanie, jakie reszty mozna osiagnac po 1 cyklu. vector<long long> indexes; for (long long i = 0; i < div; i++) { if (costs[i] != (LLONG_MAX/10)) { indexes.push_back(i); } } // Ponizej wzorem problemu plecakowego znajduje sie nowe mozliwosci dla roznych reszt. Konczy sie gdy po pelnym cyklu brak jest nowych wynikow. while (!indexes.empty()) { vector<long long> newCosts(div, (LLONG_MAX/10)); for (auto& i : indexes) { for (long long j = 0; j < div; j++) { if (costs[j] != (LLONG_MAX/10)) { newCosts[(i + j) % div] = min(newCosts[(i + j) % div], costs[i] + costs[j]); } } } indexes.clear(); for (long long j = 0; j < div; j++) { if (newCosts[j] < costs[j]) { costs[j] = newCosts[j]; indexes.push_back(j); } } } // Wypisanie wyniku for (long long i = 0; i < div; i++) { if (costs[i] >= (LLONG_MAX/10)) { cout << -1 << '\n'; } else { cout << costs[i] << '\n'; } } return 0; } |