#include <iostream> #include <vector> #include <algorithm> #include <map> #include <unordered_map> #include <cstdint> #include <limits> struct RodzajZelka { // int kolor; int64_t koszt; int16_t waga; }; static std::string nl{"\n"}; static int64_t INF = std::numeric_limits<int64_t>::max(); typedef std::vector<RodzajZelka> RodzajeZelkow; typedef std::vector<RodzajeZelkow> KoloroweZelki; typedef std::unordered_map<int32_t,int64_t> WagaWKoszt; void dodaj_do_zestawu(WagaWKoszt &zestawy, RodzajeZelkow &rodzaje, int16_t m) { WagaWKoszt wynik; for (auto &mniejszy: zestawy) { for (RodzajZelka &zelek: rodzaje) { int32_t waga_wiekszego = (mniejszy.first + zelek.waga) % m; int64_t koszt_wiekszego = mniejszy.second + zelek.koszt; auto znany_koszt = wynik.find(waga_wiekszego); if (znany_koszt == wynik.end() || koszt_wiekszego < znany_koszt->second) { wynik[waga_wiekszego] = koszt_wiekszego; } } } zestawy.swap(wynik); } int64_t mieszaj_zestawy(std::vector<WagaWKoszt> &mapa_zestawow, std::vector<int64_t> &wyniki) { std::vector<std::vector<RodzajZelka>> zestawy(mapa_zestawow.size()); std::vector<int> pozycje(mapa_zestawow.size()); for (size_t i=1; i<mapa_zestawow.size(); ++i) { zestawy[i].reserve(mapa_zestawow[i].size()); for (auto &zestaw: mapa_zestawow[i]) { zestawy[i].push_back({zestaw.second, zestaw.first}); // std::cerr << "<> " << i << " " << zestaw.second << "←" << zestaw.first << nl; } } int64_t najmniejszy_koszt = INF; while (true) { int32_t waga = 0; int64_t koszt = 0; for (size_t i=1; i<zestawy.size(); ++i) { RodzajZelka &zelek = zestawy[i][pozycje[i]]; koszt += zelek.koszt; waga += zelek.waga; } najmniejszy_koszt = std::min(najmniejszy_koszt, koszt); waga = waga % wyniki.size(); wyniki[waga] = std::min(wyniki[waga], koszt); for (size_t i=1; i<=pozycje.size(); ++i) { if (i == pozycje.size()) { return najmniejszy_koszt; } ++pozycje[i]; if (pozycje[i] == (int)zestawy[i].size()) { pozycje[i] = 0; } else { break; } } } return najmniejszy_koszt; } int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); int rodzajow; int kolorow; int m; std::cin >> rodzajow >> kolorow >> m; KoloroweZelki rodzaje(kolorow+1); std::vector<WagaWKoszt> zestawy(kolorow+1); std::vector<int64_t> wyniki(m, INF); wyniki[0] = 0; int16_t kolor; int16_t waga; int64_t koszt; for (int i=0; i<rodzajow; ++i) { std::cin >> kolor >> waga >> koszt; rodzaje[kolor].emplace_back(koszt, waga); } for (int i=1; i<=kolorow; ++i) { zestawy[i].emplace(0, 0); if (rodzaje[i].size() == 0) { goto wypisz_wynik; } } for (int i=1; i<=m; ++i) { for (int j=1; j<=kolorow; ++j) { dodaj_do_zestawu(zestawy[j], rodzaje[j], m); // std::cerr << "kolor " << j << " wielkość zestawu " << i << nl; // for (auto &zestaw: zestawy[j]) { // std::cerr << zestaw.first << "->" << zestaw.second << " "; // } // std::cerr << nl; } int64_t najmn = mieszaj_zestawy(zestawy, wyniki); if (*std::max_element(wyniki.begin(), wyniki.end()) <= najmn) { goto wypisz_wynik; } } // std::cerr << "---" << nl; wypisz_wynik:; for (int i=0; i<m; ++i) { if (wyniki[i] == INF) { wyniki[i] = -1; } std::cout << wyniki[i] << nl; } }
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 118 119 120 121 122 123 124 125 126 127 128 | #include <iostream> #include <vector> #include <algorithm> #include <map> #include <unordered_map> #include <cstdint> #include <limits> struct RodzajZelka { // int kolor; int64_t koszt; int16_t waga; }; static std::string nl{"\n"}; static int64_t INF = std::numeric_limits<int64_t>::max(); typedef std::vector<RodzajZelka> RodzajeZelkow; typedef std::vector<RodzajeZelkow> KoloroweZelki; typedef std::unordered_map<int32_t,int64_t> WagaWKoszt; void dodaj_do_zestawu(WagaWKoszt &zestawy, RodzajeZelkow &rodzaje, int16_t m) { WagaWKoszt wynik; for (auto &mniejszy: zestawy) { for (RodzajZelka &zelek: rodzaje) { int32_t waga_wiekszego = (mniejszy.first + zelek.waga) % m; int64_t koszt_wiekszego = mniejszy.second + zelek.koszt; auto znany_koszt = wynik.find(waga_wiekszego); if (znany_koszt == wynik.end() || koszt_wiekszego < znany_koszt->second) { wynik[waga_wiekszego] = koszt_wiekszego; } } } zestawy.swap(wynik); } int64_t mieszaj_zestawy(std::vector<WagaWKoszt> &mapa_zestawow, std::vector<int64_t> &wyniki) { std::vector<std::vector<RodzajZelka>> zestawy(mapa_zestawow.size()); std::vector<int> pozycje(mapa_zestawow.size()); for (size_t i=1; i<mapa_zestawow.size(); ++i) { zestawy[i].reserve(mapa_zestawow[i].size()); for (auto &zestaw: mapa_zestawow[i]) { zestawy[i].push_back({zestaw.second, zestaw.first}); // std::cerr << "<> " << i << " " << zestaw.second << "←" << zestaw.first << nl; } } int64_t najmniejszy_koszt = INF; while (true) { int32_t waga = 0; int64_t koszt = 0; for (size_t i=1; i<zestawy.size(); ++i) { RodzajZelka &zelek = zestawy[i][pozycje[i]]; koszt += zelek.koszt; waga += zelek.waga; } najmniejszy_koszt = std::min(najmniejszy_koszt, koszt); waga = waga % wyniki.size(); wyniki[waga] = std::min(wyniki[waga], koszt); for (size_t i=1; i<=pozycje.size(); ++i) { if (i == pozycje.size()) { return najmniejszy_koszt; } ++pozycje[i]; if (pozycje[i] == (int)zestawy[i].size()) { pozycje[i] = 0; } else { break; } } } return najmniejszy_koszt; } int main() { std::ios_base::sync_with_stdio(false); std::cin.tie(nullptr); int rodzajow; int kolorow; int m; std::cin >> rodzajow >> kolorow >> m; KoloroweZelki rodzaje(kolorow+1); std::vector<WagaWKoszt> zestawy(kolorow+1); std::vector<int64_t> wyniki(m, INF); wyniki[0] = 0; int16_t kolor; int16_t waga; int64_t koszt; for (int i=0; i<rodzajow; ++i) { std::cin >> kolor >> waga >> koszt; rodzaje[kolor].emplace_back(koszt, waga); } for (int i=1; i<=kolorow; ++i) { zestawy[i].emplace(0, 0); if (rodzaje[i].size() == 0) { goto wypisz_wynik; } } for (int i=1; i<=m; ++i) { for (int j=1; j<=kolorow; ++j) { dodaj_do_zestawu(zestawy[j], rodzaje[j], m); // std::cerr << "kolor " << j << " wielkość zestawu " << i << nl; // for (auto &zestaw: zestawy[j]) { // std::cerr << zestaw.first << "->" << zestaw.second << " "; // } // std::cerr << nl; } int64_t najmn = mieszaj_zestawy(zestawy, wyniki); if (*std::max_element(wyniki.begin(), wyniki.end()) <= najmn) { goto wypisz_wynik; } } // std::cerr << "---" << nl; wypisz_wynik:; for (int i=0; i<m; ++i) { if (wyniki[i] == INF) { wyniki[i] = -1; } std::cout << wyniki[i] << nl; } } |