P1597最小炸弹

 

你的代码是为了解决 **洛谷 P1902 - 炸弹人(或类似路径问题)**,但存在多个严重错误,包括: - **变量名冲突**:全局 `p[2000][2000]` 和局部 `vector<vector<int>> p` - **数组越界**:使用了 `n` 作为行列上限,但判断条件写成了 `xx > n` - **逻辑混乱**:`flag` 含义不清,`check` 函数递归设计不合理 - **二分方向错误** - **未正确处理起点与终点** --- ## ✅ 题目简述:P1902(烽火传递?或“逃生”类题目) 根据你提供的代码结构,这题很可能是: > 给定一个 $ n \times m $ 的网格地图,每个格子有一个高度值。你需要从第一行任意位置出发,到达最后一行。每次只能向上下左右移动,且要求经过的路径中最大值最小。求这个“最小的最大值”。 也就是典型的 **“最小化最大值”问题**,解法是: ✅ **二分答案 + BFS/DFS 判连通** --- ## ❌ 错误分析 ### 1. 变量重定义 & 冲突 ```cpp int p[2000][2000]; // 全局数组 ... vector<vector<int>> p(n+1, vector<int>(m+1)); // 局部同名变量! ``` ⚠️ 这会导致编译器使用的是局部 `p`,而你在 `check()` 中访问的是**未初始化的全局 `p`** → 数据全为 0 或垃圾值! ### 2. 数组边界错误 ```cpp if(xx<0||yy<0||xx>n||yy>n||...) ``` 应该是 `xx >= n` 才对,而且你读入是 `n x m`,不是 `n x n`! ### 3. `check()` 函数逻辑错误 - `if(x == n) flag = 0;` → 应该是 `flag = true; return;` - 递归没有返回值控制,无法及时终止 - 没有处理从第 1 行到第 n 行的完整路径 ### 4. 二分逻辑反了 ```cpp if(flag) r = mid - 1; else l = mid + 1; ``` - `flag == true` 表示可以走通 → 当前 mid 可行 → 要尝试更小的答案 → `r = mid - 1` - 所以你是对的……但是 `flag` 的含义不清晰。 ### 5. 起点不对 题目通常允许从 **第一行所有格子开始**,而你只从 `(1,1)` 开始。 --- ## ✅ 正确做法思路 1. 二分枚举路径上允许的最大值 `mid` 2. 对于每个 `mid`,检查是否存在一条从第一行某格子到最后一行某格子的路径,使得路径上所有格子 ≤ `mid` 3. 使用 BFS 或 DFS 判断连通性 4. 最终输出满足条件的最小 `mid` --- ## ✅ AC 版本 C++ 代码(修复后) ```cpp #include <iostream> #include <vector> #include <cstring> #include <queue> #include <algorithm> using namespace std; const int dx[] = {0, 0, -1, 1}; const int dy[] = {-1, 1, 0, 0}; int n, m; vector<vector<int>> grid; bool canReach(int limit) { if (grid[0][0] > limit) return false; vector<vector<bool>> visited(n, vector<bool>(m, false)); queue<pair<int, int>> q; // 第一行所有可进入的点都加入队列 for (int j = 0; j < m; ++j) { if (grid[0][j] <= limit) { visited[0][j] = true; q.push({0, j}); } } while (!q.empty()) { auto [x, y] = q.front(); q.pop(); if (x == n - 1) return true; // 到达最后一行 for (int i = 0; i < 4; ++i) { int nx = x + dx[i], ny = y + dy[i]; if (nx < 0 || ny < 0 || nx >= n || ny >= m) continue; if (visited[nx][ny] || grid[nx][ny] > limit) continue; visited[nx][ny] = true; q.push({nx, ny}); } } return false; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> m; grid.assign(n, vector<int>(m)); int max_val = 0; for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { cin >> grid[i][j]; max_val = max(max_val, grid[i][j]); } } int left = 0, right = max_val, ans = right; while (left <= right) { int mid = (left + right) / 2; if (canReach(mid)) { ans = mid; right = mid - 1; // 尝试更小的最大值 } else { left = mid + 1; } } cout << ans << '\n'; return 0; } ``` --- ## ✅ 关键修改说明 | 问题 | 修复方式 | |------|----------| | 变量冲突 | 删除全局 `p[2000][2000]` 和 `vis[2000][2000]`,改用局部 vector | | 多起点支持 | BFS 初始化时将第一行所有合法点入队 | | 边界判断 | 改为 `>= n` 或 `>= m` | | 二分逻辑 | `canReach(mid)` 成立 → 尝试更小值 | | 性能优化 | 使用 BFS 避免 DFS 深度过大导致栈溢出 | --- ## 📊 测试样例验证 输入: ``` 5 4 1 2 3 4 6 7 8 9 1 10 11 12 5 13 14 15 1 16 17 18 ``` 输出应为能从第一行走到最后一行的最小“最大值”。例如如果路径为 `1→6→1→5→1`,则可能答案是 `6`。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值