#include <iostream> #include <algorithm> #include <utility> #include <string> #include <vector> #include <cassert> using namespace std; const int INF = 10'000'000; struct Stan { int poczatek = 0; int koszt = 0; }; ostream& operator<<(ostream& os, Stan const& s) { os << "{" << s.poczatek << " " << s.koszt << "$}"; return os; } struct Bufor { bool gotowy = false; vector< Stan > wektor_stanow; }; struct Plan { vector< int > miasta; vector< long long > moc_ogona; vector< int > koszt_ogona; vector< int > znaczace; vector< Bufor > BUFOR_STANOW; }; Plan PL; bool inline ogon_ma_moc(int); void wczytaj_plan(int lmiast) { lmiast += 1; //wartownik PL.miasta.resize(lmiast); for( int i = 0; i < lmiast; ++i ) { cin >> PL.miasta[i]; } PL.moc_ogona.resize(lmiast); PL.moc_ogona.back() = PL.miasta.back(); for( int i = lmiast - 2; 0 <= i; --i ) { PL.moc_ogona[i] = PL.moc_ogona[i+1] + PL.miasta[i]; } PL.koszt_ogona.resize(lmiast); fill(PL.koszt_ogona.begin(), PL.koszt_ogona.end(), -1); for( int i = 0; i < lmiast - 1; ++i ) { if( PL.miasta[i] != 0 ) { PL.znaczace.push_back(i); } } PL.BUFOR_STANOW.resize(lmiast); } bool inline jest_fabryka(int i) { return PL.miasta[i] < 0; } bool inline jest_pusto(int i) { return PL.miasta[i] == 0; } bool inline ogon_ma_moc(int i) { return 0 <= PL.moc_ogona[i]; } bool inline mam_zapamietany_ogon(int i) { return PL.koszt_ogona[i] != -1; } int inline podaj_koszt_ogona(int i) { return PL.koszt_ogona[i]; } void inline zapamietaj_koszt_ogona( int i, int koszt) { PL.koszt_ogona[i] = koszt; } int pierwszy_znaczacy( int i ) { auto it = lower_bound( PL.znaczace.begin(), PL.znaczace.end(), i); return it - PL.znaczace.begin(); } vector< int > daj_poczatki( int poczatek) { vector< int > wynik; for( int indeks_i = pierwszy_znaczacy(poczatek); indeks_i < PL.znaczace.size(); ++indeks_i) { int i = PL.znaczace[indeks_i]; wynik.push_back(i); if(jest_fabryka(i)) { return wynik; } } wynik.clear(); return wynik; } void dopelniaj_poczatek_stara_fja( int poczatek, vector< Stan >& stany ) { long long moc = 0LL; bool brak_mocy = false; for( int indeks_i = pierwszy_znaczacy(poczatek); indeks_i < PL.znaczace.size(); ++indeks_i) { int i = PL.znaczace[indeks_i]; moc += static_cast< long long >(PL.miasta[i]); if (jest_fabryka(i) ) { if( (moc >= 0) && ogon_ma_moc(i+1)) { stany.push_back( Stan { i + 1, i - poczatek}); brak_mocy = false; } else { brak_mocy = true; } } else { // elektrownia if ( (brak_mocy) && (0 <= moc) && ogon_ma_moc(i+1)) { stany.push_back( Stan {i + 1, i - poczatek}); brak_mocy = false; } } } } void dopelniaj_poczatek( int const poczatek) { if (! PL.BUFOR_STANOW[poczatek].gotowy ) { dopelniaj_poczatek_stara_fja(poczatek, PL.BUFOR_STANOW[poczatek].wektor_stanow); PL.BUFOR_STANOW[poczatek].gotowy = true; } } void dopelniaj_poczatki( vector< int > const& poczatki ) { for( auto&& p: poczatki) { dopelniaj_poczatek(p); } } int pelny_koszt(Stan s) { if(mam_zapamietany_ogon(s.poczatek)) { return(podaj_koszt_ogona(s.poczatek)); } vector< int > poczatki = daj_poczatki(s.poczatek); if(poczatki.size() == 0) { return 0; } dopelniaj_poczatki(poczatki); int najlepszy = INF; for (auto&& p : poczatki) { for( auto&& m : PL.BUFOR_STANOW[p].wektor_stanow ) { int wynik = pelny_koszt(m); najlepszy = min(najlepszy, m.koszt + wynik); } } zapamietaj_koszt_ogona(s.poczatek, najlepszy); return najlepszy; } int main() { ios::sync_with_stdio(false); int lmiast; cin >> lmiast; wczytaj_plan(lmiast); Stan s = {0, 0}; int wynik = pelny_koszt(s); wynik = (wynik == INF) ? -1 : wynik; cout << wynik << endl; 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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | #include <iostream> #include <algorithm> #include <utility> #include <string> #include <vector> #include <cassert> using namespace std; const int INF = 10'000'000; struct Stan { int poczatek = 0; int koszt = 0; }; ostream& operator<<(ostream& os, Stan const& s) { os << "{" << s.poczatek << " " << s.koszt << "$}"; return os; } struct Bufor { bool gotowy = false; vector< Stan > wektor_stanow; }; struct Plan { vector< int > miasta; vector< long long > moc_ogona; vector< int > koszt_ogona; vector< int > znaczace; vector< Bufor > BUFOR_STANOW; }; Plan PL; bool inline ogon_ma_moc(int); void wczytaj_plan(int lmiast) { lmiast += 1; //wartownik PL.miasta.resize(lmiast); for( int i = 0; i < lmiast; ++i ) { cin >> PL.miasta[i]; } PL.moc_ogona.resize(lmiast); PL.moc_ogona.back() = PL.miasta.back(); for( int i = lmiast - 2; 0 <= i; --i ) { PL.moc_ogona[i] = PL.moc_ogona[i+1] + PL.miasta[i]; } PL.koszt_ogona.resize(lmiast); fill(PL.koszt_ogona.begin(), PL.koszt_ogona.end(), -1); for( int i = 0; i < lmiast - 1; ++i ) { if( PL.miasta[i] != 0 ) { PL.znaczace.push_back(i); } } PL.BUFOR_STANOW.resize(lmiast); } bool inline jest_fabryka(int i) { return PL.miasta[i] < 0; } bool inline jest_pusto(int i) { return PL.miasta[i] == 0; } bool inline ogon_ma_moc(int i) { return 0 <= PL.moc_ogona[i]; } bool inline mam_zapamietany_ogon(int i) { return PL.koszt_ogona[i] != -1; } int inline podaj_koszt_ogona(int i) { return PL.koszt_ogona[i]; } void inline zapamietaj_koszt_ogona( int i, int koszt) { PL.koszt_ogona[i] = koszt; } int pierwszy_znaczacy( int i ) { auto it = lower_bound( PL.znaczace.begin(), PL.znaczace.end(), i); return it - PL.znaczace.begin(); } vector< int > daj_poczatki( int poczatek) { vector< int > wynik; for( int indeks_i = pierwszy_znaczacy(poczatek); indeks_i < PL.znaczace.size(); ++indeks_i) { int i = PL.znaczace[indeks_i]; wynik.push_back(i); if(jest_fabryka(i)) { return wynik; } } wynik.clear(); return wynik; } void dopelniaj_poczatek_stara_fja( int poczatek, vector< Stan >& stany ) { long long moc = 0LL; bool brak_mocy = false; for( int indeks_i = pierwszy_znaczacy(poczatek); indeks_i < PL.znaczace.size(); ++indeks_i) { int i = PL.znaczace[indeks_i]; moc += static_cast< long long >(PL.miasta[i]); if (jest_fabryka(i) ) { if( (moc >= 0) && ogon_ma_moc(i+1)) { stany.push_back( Stan { i + 1, i - poczatek}); brak_mocy = false; } else { brak_mocy = true; } } else { // elektrownia if ( (brak_mocy) && (0 <= moc) && ogon_ma_moc(i+1)) { stany.push_back( Stan {i + 1, i - poczatek}); brak_mocy = false; } } } } void dopelniaj_poczatek( int const poczatek) { if (! PL.BUFOR_STANOW[poczatek].gotowy ) { dopelniaj_poczatek_stara_fja(poczatek, PL.BUFOR_STANOW[poczatek].wektor_stanow); PL.BUFOR_STANOW[poczatek].gotowy = true; } } void dopelniaj_poczatki( vector< int > const& poczatki ) { for( auto&& p: poczatki) { dopelniaj_poczatek(p); } } int pelny_koszt(Stan s) { if(mam_zapamietany_ogon(s.poczatek)) { return(podaj_koszt_ogona(s.poczatek)); } vector< int > poczatki = daj_poczatki(s.poczatek); if(poczatki.size() == 0) { return 0; } dopelniaj_poczatki(poczatki); int najlepszy = INF; for (auto&& p : poczatki) { for( auto&& m : PL.BUFOR_STANOW[p].wektor_stanow ) { int wynik = pelny_koszt(m); najlepszy = min(najlepszy, m.koszt + wynik); } } zapamietaj_koszt_ogona(s.poczatek, najlepszy); return najlepszy; } int main() { ios::sync_with_stdio(false); int lmiast; cin >> lmiast; wczytaj_plan(lmiast); Stan s = {0, 0}; int wynik = pelny_koszt(s); wynik = (wynik == INF) ? -1 : wynik; cout << wynik << endl; return 0; } |