#include <bits/stdc++.h> using namespace std; struct Position { size_t row, column; }; struct Bool { bool value; operator bool() const { return value; } void operator=(bool v) { value = v; } }; template <typename T> struct Board { size_t row_count, column_count; vector<vector<T>> rows; Board() : Board(0, 0) {} Board(size_t row_count, size_t column_count) { this->row_count = row_count; this->column_count = column_count; rows.resize(row_count); for (auto& row : rows) row.resize(column_count); } T& operator[](Position p) { return rows[p.row][p.column]; } T operator[](Position p) const { return rows[p.row][p.column]; } bool contains(size_t row, size_t column) const { return row < row_count && column < column_count; } bool contains(Position p) const { return contains(p.row, p.column); } struct Iterator { Board& board; size_t row, column; Iterator(Board& board, size_t row, size_t column) : board(board) { this->row = row; this->column = column; } T& operator*() { return board[Position{row, column}]; } Iterator operator++() { row += (column + 1) / board.column_count; column = (column + 1) % board.column_count; return *this; } bool operator!=(const Iterator& rhs) const { return row != rhs.row || column != rhs.column; } }; Iterator begin() { return {*this, 0, 0}; } Iterator end() { return {*this, row_count, 0}; } }; enum class Field { Safe, Danger }; struct Contestant { long long speed_uphill, speed_downhill; }; struct TestCase { Board<Field> board; size_t contestant_count; vector<Contestant> contestants; }; TestCase read_test_case(); void solve_test_case(const TestCase&); int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); solve_test_case(read_test_case()); } TestCase read_test_case() { TestCase test_case; size_t row_count, column_count; cin >> row_count >> column_count >> test_case.contestant_count; test_case.board = Board<Field>(row_count, column_count); for (auto& f : test_case.board) { char c; cin >> c; if (c == '.') f = Field::Safe; else f = Field::Danger; } test_case.contestants.resize(test_case.contestant_count); for (auto& c : test_case.contestants) cin >> c.speed_uphill >> c.speed_downhill; return test_case; } struct Path { long long uphill_moves, downhill_moves; }; Path find_shortest_path(const Board<Field>& board); void solve_test_case(const TestCase& test_case) { Path path = find_shortest_path(test_case.board); long long min_time = numeric_limits<long long>::max(); long long min_count = 0; for (auto c : test_case.contestants) { long long time = path.uphill_moves * c.speed_uphill + path.downhill_moves * c.speed_downhill; if (time < min_time) { min_time = time; min_count = 0; } if (time == min_time) min_count++; } cout << min_time << " " << min_count << "\n"; } Path find_shortest_path(const Board<Field>& board) { Board<Bool> visited(board.row_count, board.column_count); Board<Path> path_to(board.row_count, board.column_count); queue<Position> awaiting; awaiting.push({0, 0}); visited[{0, 0}] = true; path_to[{0, 0}] = {0, 0}; while (!awaiting.empty()) { auto current = awaiting.front(); awaiting.pop(); for (int dr = -1; dr <= 1; dr++) for (int dc = -1; dc <= 1; dc++) { if (dr * dr == dc * dc) continue; Position n = {current.row + dr, current.column + dc}; if (!board.contains(n)) continue; if (visited[n]) continue; if (board[n] == Field::Danger) continue; visited[n] = true; Path current_path = path_to[current]; int delta_uphill = (dr > 0 || dc > 0); int delta_downhill = (dr < 0 || dc < 0); path_to[n] = { current_path.uphill_moves + delta_uphill, current_path.downhill_moves + delta_downhill}; awaiting.push(n); } } return path_to[{board.row_count - 1, board.column_count - 1}]; }
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 | #include <bits/stdc++.h> using namespace std; struct Position { size_t row, column; }; struct Bool { bool value; operator bool() const { return value; } void operator=(bool v) { value = v; } }; template <typename T> struct Board { size_t row_count, column_count; vector<vector<T>> rows; Board() : Board(0, 0) {} Board(size_t row_count, size_t column_count) { this->row_count = row_count; this->column_count = column_count; rows.resize(row_count); for (auto& row : rows) row.resize(column_count); } T& operator[](Position p) { return rows[p.row][p.column]; } T operator[](Position p) const { return rows[p.row][p.column]; } bool contains(size_t row, size_t column) const { return row < row_count && column < column_count; } bool contains(Position p) const { return contains(p.row, p.column); } struct Iterator { Board& board; size_t row, column; Iterator(Board& board, size_t row, size_t column) : board(board) { this->row = row; this->column = column; } T& operator*() { return board[Position{row, column}]; } Iterator operator++() { row += (column + 1) / board.column_count; column = (column + 1) % board.column_count; return *this; } bool operator!=(const Iterator& rhs) const { return row != rhs.row || column != rhs.column; } }; Iterator begin() { return {*this, 0, 0}; } Iterator end() { return {*this, row_count, 0}; } }; enum class Field { Safe, Danger }; struct Contestant { long long speed_uphill, speed_downhill; }; struct TestCase { Board<Field> board; size_t contestant_count; vector<Contestant> contestants; }; TestCase read_test_case(); void solve_test_case(const TestCase&); int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); solve_test_case(read_test_case()); } TestCase read_test_case() { TestCase test_case; size_t row_count, column_count; cin >> row_count >> column_count >> test_case.contestant_count; test_case.board = Board<Field>(row_count, column_count); for (auto& f : test_case.board) { char c; cin >> c; if (c == '.') f = Field::Safe; else f = Field::Danger; } test_case.contestants.resize(test_case.contestant_count); for (auto& c : test_case.contestants) cin >> c.speed_uphill >> c.speed_downhill; return test_case; } struct Path { long long uphill_moves, downhill_moves; }; Path find_shortest_path(const Board<Field>& board); void solve_test_case(const TestCase& test_case) { Path path = find_shortest_path(test_case.board); long long min_time = numeric_limits<long long>::max(); long long min_count = 0; for (auto c : test_case.contestants) { long long time = path.uphill_moves * c.speed_uphill + path.downhill_moves * c.speed_downhill; if (time < min_time) { min_time = time; min_count = 0; } if (time == min_time) min_count++; } cout << min_time << " " << min_count << "\n"; } Path find_shortest_path(const Board<Field>& board) { Board<Bool> visited(board.row_count, board.column_count); Board<Path> path_to(board.row_count, board.column_count); queue<Position> awaiting; awaiting.push({0, 0}); visited[{0, 0}] = true; path_to[{0, 0}] = {0, 0}; while (!awaiting.empty()) { auto current = awaiting.front(); awaiting.pop(); for (int dr = -1; dr <= 1; dr++) for (int dc = -1; dc <= 1; dc++) { if (dr * dr == dc * dc) continue; Position n = {current.row + dr, current.column + dc}; if (!board.contains(n)) continue; if (visited[n]) continue; if (board[n] == Field::Danger) continue; visited[n] = true; Path current_path = path_to[current]; int delta_uphill = (dr > 0 || dc > 0); int delta_downhill = (dr < 0 || dc < 0); path_to[n] = { current_path.uphill_moves + delta_uphill, current_path.downhill_moves + delta_downhill}; awaiting.push(n); } } return path_to[{board.row_count - 1, board.column_count - 1}]; } |