#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; } |
English