結果
| 問題 | No.340 雪の足跡 |
| コンテスト | |
| ユーザー |
qwewe
|
| 提出日時 | 2025-05-14 12:59:50 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 9,997 bytes |
| コンパイル時間 | 1,062 ms |
| コンパイル使用メモリ | 89,440 KB |
| 実行使用メモリ | 7,844 KB |
| 最終ジャッジ日時 | 2025-05-14 13:01:28 |
| 合計ジャッジ時間 | 5,130 ms |
|
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 5 |
| other | AC * 15 TLE * 1 -- * 16 |
ソースコード
#include <iostream>
#include <vector>
#include <queue>
#include <utility> // Required for std::pair, though not directly used, good practice
#include <algorithm> // Required for std::min and std::max
using namespace std;
// Use int for distance. The maximum possible distance W*H-1 can be up to 10^6 - 1,
// which fits comfortably within a 32-bit signed integer.
const int INF = -1; // Use -1 to represent infinity or unreachable state.
int main() {
// Optimize C++ standard streams for faster I/O. Crucial for performance-sensitive problems.
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int W, H; // Grid dimensions: Width W, Height H
cin >> W >> H;
int N; // Number of adults
cin >> N;
// Handle the edge case where the grid is 1x1.
// In this case, Mana's home (cell 0) is the same as Mitsuru's home (cell W*H-1 = 0).
// The distance is 0. We must still read the rest of the input to avoid errors.
if (W == 1 && H == 1) {
// Consume the remaining input lines describing adult paths.
for(int i = 0; i < N; ++i) {
int M; // Number of stops for adult i
cin >> M;
int dummy; // Variable to read and discard cell indices
// An adult i's path involves M+1 points: B_i,0 (start) to B_i,M (last stop).
for(int j = 0; j <= M; ++j) {
cin >> dummy; // Read and discard each B_i,j
}
}
cout << 0 << endl; // Output the distance 0
return 0; // Exit program
}
// Calculate the total number of cells in the grid. Use long long to prevent potential overflow if W*H is large, although W*H <= 10^6 fits in int.
long long total_cells = (long long)W * H;
// Data structures to store traversability of edges between adjacent cells.
// `can_pass_horizontal[h][w]` is true if Mana can pass between cell (w, h) and cell (w+1, h).
// Dimensions are H rows by (W-1) columns. Handle W=1 case by creating a vector of size 0.
vector<vector<bool>> can_pass_horizontal(H, vector<bool>(W > 1 ? W - 1 : 0, false));
// `can_pass_vertical[h][w]` is true if Mana can pass between cell (w, h) and cell (w, h+1).
// Dimensions are (H-1) rows by W columns. Handle H=1 case by creating a vector of size 0.
vector<vector<bool>> can_pass_vertical(H > 1 ? H - 1 : 0, vector<bool>(W, false));
// Process each adult's path to mark the edges they traverse as traversable for Mana.
for (int i = 0; i < N; ++i) {
int M; // Number of stops for adult i
cin >> M;
int prev_B; // Cell index where the adult was previously located
cin >> prev_B; // Read the starting cell B_i,0 for adult i
// An adult path consists of M segments: B_i,j -> B_i,j+1 for j=0..M-1
for (int j = 0; j < M; ++j) {
int curr_B; // Cell index where the adult stops next
cin >> curr_B; // Read the next stop B_i, j+1
// Convert cell indices to (w, h) coordinates
int prev_w = prev_B % W; // Previous column
int prev_h = prev_B / W; // Previous row
int curr_w = curr_B % W; // Current column
int curr_h = curr_B / W; // Current row
// Check if the move is vertical (same column)
if (prev_w == curr_w) {
// Only process vertical moves if H > 1 (grid has vertical dimension)
if (H > 1) {
int h_start = min(prev_h, curr_h); // Starting row index for the segment
int h_end = max(prev_h, curr_h); // Ending row index for the segment
// Mark all vertical edges along the path segment as traversable.
// The edge between (prev_w, h) and (prev_w, h+1) corresponds to can_pass_vertical[h][prev_w].
for (int h = h_start; h < h_end; ++h) {
// Basic boundary check for safety, though problem constraints should guarantee valid indices.
if (h >= 0 && h < H - 1 && prev_w >= 0 && prev_w < W) {
can_pass_vertical[h][prev_w] = true;
}
}
}
// Otherwise, the move must be horizontal (guaranteed by problem constraints)
} else {
// Only process horizontal moves if W > 1 (grid has horizontal dimension)
if (W > 1) {
int w_start = min(prev_w, curr_w); // Starting column index for the segment
int w_end = max(prev_w, curr_w); // Ending column index for the segment
// Mark all horizontal edges along the path segment as traversable.
// The edge between (w, prev_h) and (w+1, prev_h) corresponds to can_pass_horizontal[prev_h][w].
for (int w = w_start; w < w_end; ++w) {
// Basic boundary check for safety.
if (prev_h >= 0 && prev_h < H && w >= 0 && w < W - 1) {
can_pass_horizontal[prev_h][w] = true;
}
}
}
}
prev_B = curr_B; // Update the previous location for the next segment calculation
}
}
// Perform Breadth-First Search (BFS) to find the shortest path from cell 0 to cell W*H-1.
vector<int> dist(total_cells, INF); // Stores the shortest distance from cell 0 to each cell. Initialize with INF (-1).
queue<int> q; // Queue for BFS traversal. Stores cell indices.
// Start BFS from cell 0 (Mana's home) if the grid has cells.
if (total_cells > 0) {
dist[0] = 0; // Distance to starting cell is 0
q.push(0); // Add starting cell to the queue
}
int final_dist = INF; // Variable to store the shortest distance found to the destination.
// BFS main loop
while (!q.empty()) {
int u_idx = q.front(); // Get the current cell index from the front of the queue
q.pop(); // Remove it from the queue
// Check if we have reached the destination cell (Mitsuru's home at index W*H - 1)
if (u_idx == total_cells - 1) {
final_dist = dist[u_idx]; // Store the distance found
break; // Found the shortest path, exit BFS loop
}
// Get coordinates of the current cell
int u_w = u_idx % W;
int u_h = u_idx / W;
// Explore neighbors using the marked passages
// Check North neighbor: (u_w, u_h + 1)
// Requires H > 1 to have a North neighbor and possibility of vertical passages.
if (H > 1 && u_h + 1 < H) { // Check boundary: Is there a cell to the North?
// Check passage: Is vertical passage between (u_w, u_h) and (u_w, u_h+1) allowed?
// Passage information is stored at can_pass_vertical[u_h][u_w].
if (can_pass_vertical[u_h][u_w]) {
int v_idx = u_w + (u_h + 1) * W; // Calculate index of the North neighbor
if (dist[v_idx] == INF) { // If neighbor has not been visited yet
dist[v_idx] = dist[u_idx] + 1; // Update distance
q.push(v_idx); // Add neighbor to the queue
}
}
}
// Check South neighbor: (u_w, u_h - 1)
// Requires H > 1 for South neighbor / vertical passages.
if (H > 1 && u_h - 1 >= 0) { // Check boundary: Is there a cell to the South?
// Check passage: Is vertical passage between (u_w, u_h-1) and (u_w, u_h) allowed?
// Passage information is stored at can_pass_vertical[u_h - 1][u_w].
if (can_pass_vertical[u_h - 1][u_w]) {
int v_idx = u_w + (u_h - 1) * W; // Calculate index of the South neighbor
if (dist[v_idx] == INF) { // If neighbor not visited
dist[v_idx] = dist[u_idx] + 1;
q.push(v_idx);
}
}
}
// Check East neighbor: (u_w + 1, u_h)
// Requires W > 1 for East neighbor / horizontal passages.
if (W > 1 && u_w + 1 < W) { // Check boundary: Is there a cell to the East?
// Check passage: Is horizontal passage between (u_w, u_h) and (u_w+1, u_h) allowed?
// Passage information is stored at can_pass_horizontal[u_h][u_w].
if (can_pass_horizontal[u_h][u_w]) {
int v_idx = (u_w + 1) + u_h * W; // Calculate index of the East neighbor
if (dist[v_idx] == INF) { // If neighbor not visited
dist[v_idx] = dist[u_idx] + 1;
q.push(v_idx);
}
}
}
// Check West neighbor: (u_w - 1, u_h)
// Requires W > 1 for West neighbor / horizontal passages.
if (W > 1 && u_w - 1 >= 0) { // Check boundary: Is there a cell to the West?
// Check passage: Is horizontal passage between (u_w-1, u_h) and (u_w, u_h) allowed?
// Passage information is stored at can_pass_horizontal[u_h][u_w - 1].
if (can_pass_horizontal[u_h][u_w - 1]) {
int v_idx = (u_w - 1) + u_h * W; // Calculate index of the West neighbor
if (dist[v_idx] == INF) { // If neighbor not visited
dist[v_idx] = dist[u_idx] + 1;
q.push(v_idx);
}
}
}
}
// Output the final result based on whether the destination was reached.
if (final_dist != INF) {
cout << final_dist << endl; // Output the shortest distance found
} else {
// If destination is unreachable (and W*H > 1, because the W=1 H=1 case was handled earlier)
cout << "Odekakedekinai.." << endl; // Output the "cannot go out" message
}
return 0; // Indicate successful execution
}
qwewe