题解
最小体力值
1 条题解
-
0
解题思路
小童走路不会拐弯,只能朝“上、下、左、右”其中一个方向直走,直到走出方阵。所以要离开方阵,一共只有 4 种走法:
- 一直往上走,经过上方一串格子;
- 一直往下走,经过下方一串格子;
- 一直往左走,经过左边一串格子;
- 一直往右走,经过右边一串格子。
每种走法里,经过的每一个 '*' 都要消耗 1 个体力。我们只要把 4 种走法的体力值都算出来,取最小的那个,就是答案。
怎么“一步一步走”呢?我们借助方向数组:
- 上:行号 -1(dx=-1),列号不变(dy=0);
- 下:行号 +1;
- 左:列号 -1;
- 右:列号 +1。
用 while 循环模拟:从起点出发,每走一步先移动一下位置,然后检查——
- 如果走出边界(行号 <1 或 >m,列号 <1 或 >n),就停下来,这条路线走完了;
- 如果没出界,再看当前位置是不是 '*',是的话体力值 +1。
小童自己站的位置是 '.',并且他走第一步就离开了原地,所以自己的格子不会计入体力值。
参考代码
// P4453 最小体力值:从起点沿上下左右四个方向直走,分别数经过的*的个数,取最小值 #include <iostream> using namespace std; char a[20][20]; // 字符方阵 int dx[4] = {-1, 1, 0, 0}; // 上下左右的行变化 int dy[4] = {0, 0, -1, 1}; // 上下左右的列变化 int main() { int m, n, x, y; cin >> m >> n; for (int i = 1; i <= m; i++) for (int j = 1; j <= n; j++) cin >> a[i][j]; // 字符之间有空格,直接逐个读 cin >> x >> y; // 小童当前所在的行和列 int ans = 1000000; // 最小体力值,先设一个大数 for (int d = 0; d < 4; d++) { // 枚举四个方向 int cnt = 0; // 本方向经过的*的个数 int i = x, j = y; while (true) { i += dx[d]; j += dy[d]; if (i < 1 || i > m || j < 1 || j > n) break; // 走出方阵,结束 if (a[i][j] == '*') cnt++; // 路过雷点消耗1体力 } if (cnt < ans) ans = cnt; // 更新最小体力值 } cout << ans << endl; return 0; }复杂度分析
- 每个方向最多走 m 或 n 步,一共 4 个方向,时间复杂度是 O(m + n)。
- 需要把整个方阵存下来,空间复杂度是 O(m × n)。
- 1