#include <iostream> #include <algorithm> #include <vector> #include <cassert> #include <chrono> #include <set> #include <unordered_set> #include <unordered_map> using namespace std; namespace ze { struct Zelek { long long kolor; long long masa; long long cena; }; std::vector<long long> obliczMinimalneDlaPojedynczych(std::vector<ze::Zelek>& zelki, long long liczbaKolorow, long long m) { std::unordered_map<long long, std::vector<Zelek>> zKoloruDoZelkow; for (auto & zelek:zelki) zKoloruDoZelkow[zelek.kolor].push_back(zelek); std::vector<long long> ceny(m, -1); ceny[0] = 0; if (zKoloruDoZelkow.size() != liczbaKolorow) return ceny; for (long long k = 1; k <= liczbaKolorow; ++k) { std::vector<long long> noweCeny(m, -1); for (auto& zelek : zKoloruDoZelkow[k]) { for (long long i = 0; i < ceny.size(); ++i) { if (ceny[i]== -1) continue; long long nowaCena = ceny[i] + zelek.cena; long long masa = (i + zelek.masa) % m; if (noweCeny[masa] == -1 || noweCeny[masa] > nowaCena) noweCeny[masa] = nowaCena; } } ceny = noweCeny; } return ceny; } std::vector<long long> obliczMinimalneOdleglosci(std::vector<long long> & krawedzie, long long m) { std::vector<long long> minimalnaOdleglosc(m, -1); minimalnaOdleglosc[0] = 0; std::vector<bool> czyPewny(m, false); bool stop = false; while (true) { long long minimum = -1; long long minimumIndex = -1; for (long long i = 0; i < m; ++i) { if (czyPewny[i]) continue; if (minimalnaOdleglosc[i] == -1) continue; if (minimumIndex == -1 || minimum > minimalnaOdleglosc[i]) { minimum = minimalnaOdleglosc[i]; minimumIndex = i; } } if (minimumIndex == -1) break; czyPewny[minimumIndex] = true; for (long long i = 0; i < m; ++i) { if (krawedzie[i] == -1) continue; long long wierzcholek = (minimumIndex + i) % m; if (czyPewny[wierzcholek]) continue; long long dlugosc = minimalnaOdleglosc[minimumIndex] + krawedzie[i]; if (minimalnaOdleglosc[wierzcholek] == -1 || dlugosc < minimalnaOdleglosc[wierzcholek]) minimalnaOdleglosc[wierzcholek] = dlugosc; } } return minimalnaOdleglosc; } } int main() { ios::sync_with_stdio(false); std::cin.tie(NULL); long long liczbaZelkow; long long liczbaKolorow; long long m; std::cin >> liczbaZelkow >> liczbaKolorow >> m; std::vector<ze::Zelek> zelki; for (long long i = 0; i < liczbaZelkow; ++i) { ze::Zelek zelek; std::cin >> zelek.kolor >> zelek.masa >> zelek.cena; zelki.push_back(zelek); } std::vector<long long> minimalneDlaPojedynczych = ze::obliczMinimalneDlaPojedynczych(zelki, liczbaKolorow, m); std::vector<long long> minimalne = ze::obliczMinimalneOdleglosci(minimalneDlaPojedynczych, m); for (long long i = 0; i < minimalne.size(); ++i) { std::cout << minimalne[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 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 115 116 117 | #include <iostream> #include <algorithm> #include <vector> #include <cassert> #include <chrono> #include <set> #include <unordered_set> #include <unordered_map> using namespace std; namespace ze { struct Zelek { long long kolor; long long masa; long long cena; }; std::vector<long long> obliczMinimalneDlaPojedynczych(std::vector<ze::Zelek>& zelki, long long liczbaKolorow, long long m) { std::unordered_map<long long, std::vector<Zelek>> zKoloruDoZelkow; for (auto & zelek:zelki) zKoloruDoZelkow[zelek.kolor].push_back(zelek); std::vector<long long> ceny(m, -1); ceny[0] = 0; if (zKoloruDoZelkow.size() != liczbaKolorow) return ceny; for (long long k = 1; k <= liczbaKolorow; ++k) { std::vector<long long> noweCeny(m, -1); for (auto& zelek : zKoloruDoZelkow[k]) { for (long long i = 0; i < ceny.size(); ++i) { if (ceny[i]== -1) continue; long long nowaCena = ceny[i] + zelek.cena; long long masa = (i + zelek.masa) % m; if (noweCeny[masa] == -1 || noweCeny[masa] > nowaCena) noweCeny[masa] = nowaCena; } } ceny = noweCeny; } return ceny; } std::vector<long long> obliczMinimalneOdleglosci(std::vector<long long> & krawedzie, long long m) { std::vector<long long> minimalnaOdleglosc(m, -1); minimalnaOdleglosc[0] = 0; std::vector<bool> czyPewny(m, false); bool stop = false; while (true) { long long minimum = -1; long long minimumIndex = -1; for (long long i = 0; i < m; ++i) { if (czyPewny[i]) continue; if (minimalnaOdleglosc[i] == -1) continue; if (minimumIndex == -1 || minimum > minimalnaOdleglosc[i]) { minimum = minimalnaOdleglosc[i]; minimumIndex = i; } } if (minimumIndex == -1) break; czyPewny[minimumIndex] = true; for (long long i = 0; i < m; ++i) { if (krawedzie[i] == -1) continue; long long wierzcholek = (minimumIndex + i) % m; if (czyPewny[wierzcholek]) continue; long long dlugosc = minimalnaOdleglosc[minimumIndex] + krawedzie[i]; if (minimalnaOdleglosc[wierzcholek] == -1 || dlugosc < minimalnaOdleglosc[wierzcholek]) minimalnaOdleglosc[wierzcholek] = dlugosc; } } return minimalnaOdleglosc; } } int main() { ios::sync_with_stdio(false); std::cin.tie(NULL); long long liczbaZelkow; long long liczbaKolorow; long long m; std::cin >> liczbaZelkow >> liczbaKolorow >> m; std::vector<ze::Zelek> zelki; for (long long i = 0; i < liczbaZelkow; ++i) { ze::Zelek zelek; std::cin >> zelek.kolor >> zelek.masa >> zelek.cena; zelki.push_back(zelek); } std::vector<long long> minimalneDlaPojedynczych = ze::obliczMinimalneDlaPojedynczych(zelki, liczbaKolorow, m); std::vector<long long> minimalne = ze::obliczMinimalneOdleglosci(minimalneDlaPojedynczych, m); for (long long i = 0; i < minimalne.size(); ++i) { std::cout << minimalne[i] << "\n"; } return 0; } |