Niestety, nie byliśmy w stanie w pełni poprawnie wyświetlić tego pliku, ponieważ nie jest zakodowany w UTF-8.
Możesz pobrać ten plik i spróbować otworzyć go samodzielnie.
//Wycieczka g�rska - 4C, PA 2020 #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <climits> #include <stdio.h> #include <iostream> #include <string.h> #include <math.h> #include <algorithm> #include <vector> #include <queue> #include <map> typedef long long lLong; typedef unsigned long uLong; typedef unsigned long long ulLong; typedef unsigned int uInt; typedef unsigned char Byte; typedef std::vector<int> VI; typedef std::vector<bool> VBit; typedef std::vector<VBit> VVBit; typedef std::vector<char> VC; typedef std::vector<VC> VVC; typedef std::pair<lLong, lLong> VPLL; typedef std::vector<VPLL> VVPLL; typedef std::pair<int, int> RowCol; typedef std::queue<RowCol*> RowColQ; typedef std::vector<RowCol*> RowColV; typedef struct GoraDol { public: int Gora; //ile razy sciezka wymaga pojscia w gore int Dol; //ile razy sciezka wymaga pojscia w dol } GoraDol; using namespace std; // tablice z kierunkami ruchow dla BFS VI kierWie = { -1, 1, 0, 0 }; VI kierKol = { 0, 0, 1, -1 }; class PrzypadekTestowy { private: FILE* _input; int _n, _m; RowColV _sciezka; //przebyta trasa oryginalna inline void WczytajTrojkeInt(int* v1, int *v2, int *v3) { auto _ = fscanf(_input, "%d %d %d", v1, v2, v3); } inline void WczytajChar(char* value) { auto _ = fscanf(_input, "%c", value); } inline void WczytajParelLong(lLong* v1, lLong *v2) { auto _ = fscanf(_input, "%lld %lld", v1, v2); } inline void WyczyscNewLine() { auto _ = fscanf(_input, "\n"); } // zwraca liczbe sasiadow dodanych do kolejki inline int DodajSasiadow(VVC& mapa, RowCol &rc, RowColQ &q, VVBit& odwiedzone) { int ileDodano = 0; for (int i = 0; i < 4; i++) { int sasiadWieIdx = rc.first + kierWie[i]; int sasiadKolIdx = rc.second + kierKol[i]; if (sasiadWieIdx < 0 || sasiadKolIdx < 0) continue; if (sasiadWieIdx >=_n || sasiadKolIdx >= _m) continue; if (odwiedzone[sasiadWieIdx][sasiadKolIdx]) continue; if (mapa[sasiadWieIdx][sasiadKolIdx] == 'X') continue; // sasiad prawidlowy - dorzuc do kolejki do sprawdzenia q.push(new RowCol(sasiadWieIdx, sasiadKolIdx)); odwiedzone[sasiadWieIdx][sasiadKolIdx] = true; ileDodano++; } return ileDodano; } inline void BFS(VVC& mapa) { bool czyKoniec = false; RowCol wStart = { 0,0 }, wKoniec = { _n-1,_m-1 }; // poczatek i koniec sciezki na mapie RowColQ q; //kolejka do przechowania sciezek do sprawdzenia VVBit odwiedzone = VVBit(_n, VBit(_m, false)); int ileKrokow = 0, ileWezlowCur = 1, ileWezlowNext = 0; q.push(&wStart); odwiedzone[wStart.first][wStart.second] = true; while (!q.empty()) { RowCol &rc = *q.front(); q.pop(); if (rc == wKoniec) { czyKoniec = true; _sciezka.push_back(new RowCol(rc)); break; } int ileDodano = DodajSasiadow(mapa, rc, q, odwiedzone); ileWezlowNext += ileDodano; //dodajemy do celow backtrackingu if (ileDodano > 0) { _sciezka.push_back(new RowCol(rc)); } ileWezlowCur--; if (ileWezlowCur == 0) { ileWezlowCur = ileWezlowNext; ileWezlowNext = 0; ileKrokow++; } } } inline GoraDol WyznaczKierunki() { GoraDol result = {0,0}; // na podstawie przetestowanej sciezki wyznacz kierunki ilosciowy (bactracking) RowCol* prev = NULL; for (auto k=_sciezka.rbegin();k!=_sciezka.rend();++k) { auto cur = *k; if (prev) { // jesli nie nalezy do najkrotszej sciezki powrotnej to zignoruj punkt if (prev->first != cur->first && prev->second != cur->second) continue; if (cur->first == prev->first) //przemieszczenie w poziomie { if (cur->second < prev->second) result.Gora++; //ruch w prawo oznacza ruch w dol else result.Dol++; } else { if (cur->first < prev->first) result.Gora++; //ruch w prawo oznacza ruch w dol else result.Dol++; } } prev = cur; } return result; } public: PrzypadekTestowy(FILE* input) { _input = input; _n = 0; _m = 0; } inline void Wykonaj() { int k;//mapa nxm, liczba wedrowcow WczytajTrojkeInt(&_n, &_m, &k); WyczyscNewLine(); VVC mapa = VVC(_n, VC(_m, '.')); //rozmiar rowny liczbie mozliwych zabawek VVPLL znajomi = VVPLL(k, { 0,0 }); for (int i = 0; i < _n; i++) { for (int j = 0; j < _m; j++) { char c; WczytajChar(&c); if (c == 'X') mapa[i][j] = c; } WyczyscNewLine(); } for (int i = 0; i < k; i++) { auto z = &znajomi[i]; WczytajParelLong(&z->first, &z->second); } BFS(mapa); auto kierunki = WyznaczKierunki(); std::map<lLong, int> wyniki; lLong czasMin = LLONG_MAX; // nalicz finalne czasy dla kierunkow for (auto &z: znajomi) { lLong czas = z.first * kierunki.Gora + z.second * kierunki.Dol; wyniki[czas]++; if (czas < czasMin) czasMin = czas; } printf("%lld %d\n", czasMin,wyniki[czasMin]); } }; int main(int argc, char** argv) { FILE* in = stdin; if (argc > 1) { in = fopen(argv[1], "rt"); if (NULL == in) { in = stdin; } } PrzypadekTestowy* p = new PrzypadekTestowy(in); p->Wykonaj(); fflush(in); fclose(in); delete(p); 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 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | //Wycieczka g�rska - 4C, PA 2020 #define _CRT_SECURE_NO_WARNINGS #include <cstdio> #include <climits> #include <stdio.h> #include <iostream> #include <string.h> #include <math.h> #include <algorithm> #include <vector> #include <queue> #include <map> typedef long long lLong; typedef unsigned long uLong; typedef unsigned long long ulLong; typedef unsigned int uInt; typedef unsigned char Byte; typedef std::vector<int> VI; typedef std::vector<bool> VBit; typedef std::vector<VBit> VVBit; typedef std::vector<char> VC; typedef std::vector<VC> VVC; typedef std::pair<lLong, lLong> VPLL; typedef std::vector<VPLL> VVPLL; typedef std::pair<int, int> RowCol; typedef std::queue<RowCol*> RowColQ; typedef std::vector<RowCol*> RowColV; typedef struct GoraDol { public: int Gora; //ile razy sciezka wymaga pojscia w gore int Dol; //ile razy sciezka wymaga pojscia w dol } GoraDol; using namespace std; // tablice z kierunkami ruchow dla BFS VI kierWie = { -1, 1, 0, 0 }; VI kierKol = { 0, 0, 1, -1 }; class PrzypadekTestowy { private: FILE* _input; int _n, _m; RowColV _sciezka; //przebyta trasa oryginalna inline void WczytajTrojkeInt(int* v1, int *v2, int *v3) { auto _ = fscanf(_input, "%d %d %d", v1, v2, v3); } inline void WczytajChar(char* value) { auto _ = fscanf(_input, "%c", value); } inline void WczytajParelLong(lLong* v1, lLong *v2) { auto _ = fscanf(_input, "%lld %lld", v1, v2); } inline void WyczyscNewLine() { auto _ = fscanf(_input, "\n"); } // zwraca liczbe sasiadow dodanych do kolejki inline int DodajSasiadow(VVC& mapa, RowCol &rc, RowColQ &q, VVBit& odwiedzone) { int ileDodano = 0; for (int i = 0; i < 4; i++) { int sasiadWieIdx = rc.first + kierWie[i]; int sasiadKolIdx = rc.second + kierKol[i]; if (sasiadWieIdx < 0 || sasiadKolIdx < 0) continue; if (sasiadWieIdx >=_n || sasiadKolIdx >= _m) continue; if (odwiedzone[sasiadWieIdx][sasiadKolIdx]) continue; if (mapa[sasiadWieIdx][sasiadKolIdx] == 'X') continue; // sasiad prawidlowy - dorzuc do kolejki do sprawdzenia q.push(new RowCol(sasiadWieIdx, sasiadKolIdx)); odwiedzone[sasiadWieIdx][sasiadKolIdx] = true; ileDodano++; } return ileDodano; } inline void BFS(VVC& mapa) { bool czyKoniec = false; RowCol wStart = { 0,0 }, wKoniec = { _n-1,_m-1 }; // poczatek i koniec sciezki na mapie RowColQ q; //kolejka do przechowania sciezek do sprawdzenia VVBit odwiedzone = VVBit(_n, VBit(_m, false)); int ileKrokow = 0, ileWezlowCur = 1, ileWezlowNext = 0; q.push(&wStart); odwiedzone[wStart.first][wStart.second] = true; while (!q.empty()) { RowCol &rc = *q.front(); q.pop(); if (rc == wKoniec) { czyKoniec = true; _sciezka.push_back(new RowCol(rc)); break; } int ileDodano = DodajSasiadow(mapa, rc, q, odwiedzone); ileWezlowNext += ileDodano; //dodajemy do celow backtrackingu if (ileDodano > 0) { _sciezka.push_back(new RowCol(rc)); } ileWezlowCur--; if (ileWezlowCur == 0) { ileWezlowCur = ileWezlowNext; ileWezlowNext = 0; ileKrokow++; } } } inline GoraDol WyznaczKierunki() { GoraDol result = {0,0}; // na podstawie przetestowanej sciezki wyznacz kierunki ilosciowy (bactracking) RowCol* prev = NULL; for (auto k=_sciezka.rbegin();k!=_sciezka.rend();++k) { auto cur = *k; if (prev) { // jesli nie nalezy do najkrotszej sciezki powrotnej to zignoruj punkt if (prev->first != cur->first && prev->second != cur->second) continue; if (cur->first == prev->first) //przemieszczenie w poziomie { if (cur->second < prev->second) result.Gora++; //ruch w prawo oznacza ruch w dol else result.Dol++; } else { if (cur->first < prev->first) result.Gora++; //ruch w prawo oznacza ruch w dol else result.Dol++; } } prev = cur; } return result; } public: PrzypadekTestowy(FILE* input) { _input = input; _n = 0; _m = 0; } inline void Wykonaj() { int k;//mapa nxm, liczba wedrowcow WczytajTrojkeInt(&_n, &_m, &k); WyczyscNewLine(); VVC mapa = VVC(_n, VC(_m, '.')); //rozmiar rowny liczbie mozliwych zabawek VVPLL znajomi = VVPLL(k, { 0,0 }); for (int i = 0; i < _n; i++) { for (int j = 0; j < _m; j++) { char c; WczytajChar(&c); if (c == 'X') mapa[i][j] = c; } WyczyscNewLine(); } for (int i = 0; i < k; i++) { auto z = &znajomi[i]; WczytajParelLong(&z->first, &z->second); } BFS(mapa); auto kierunki = WyznaczKierunki(); std::map<lLong, int> wyniki; lLong czasMin = LLONG_MAX; // nalicz finalne czasy dla kierunkow for (auto &z: znajomi) { lLong czas = z.first * kierunki.Gora + z.second * kierunki.Dol; wyniki[czas]++; if (czas < czasMin) czasMin = czas; } printf("%lld %d\n", czasMin,wyniki[czasMin]); } }; int main(int argc, char** argv) { FILE* in = stdin; if (argc > 1) { in = fopen(argv[1], "rt"); if (NULL == in) { in = stdin; } } PrzypadekTestowy* p = new PrzypadekTestowy(in); p->Wykonaj(); fflush(in); fclose(in); delete(p); return 0; } |