题解:AtCoder AT_awc0048_b Footsteps in the Hallway
【题目来源】
AtCoder:B - Footsteps in the Hallway
【题目描述】
Takahashi is trying to walk through a long corridor consisting of \(N\) tiles arranged in a row. The tiles are numbered from left to right as Tile \(1\), Tile \(2\), \(\ldots\), Tile \(N\).
高桥正试图穿过一条由 \(N\) 块地砖排成一行组成的长廊。地砖从左到右编号为地砖 \(1\)、地砖 \(2\)、……、地砖 \(N\)。
Each tile is covered with dust. Initially, Tile \(i\) has dust of thickness \(H_i\). When Takahashi steps on Tile \(i\), the dust thickness on that tile becomes \(\max(0,\; H_i - D_i)\), where \(D_i\) is a non-negative integer defined for Tile \(i\). The dust thickness on tiles that Takahashi does not step on remains unchanged at the initial thickness \(H_i\).
每块地砖上都覆盖着灰尘。初始时,地砖 \(i\) 的灰尘厚度为 \(H_i\)。当高桥踩在地砖 \(i\) 上时,该地砖的灰尘厚度变为 \(\max(0,\; H_i - D_i)\),其中 \(D_i\) 是定义在地砖 \(i\) 上的非负整数。高桥没有踩到的地砖的灰尘厚度保持不变,仍为初始厚度 \(H_i\)。
Takahashi starts at Tile \(1\), and Tile \(N\) is the goal. Takahashi always moves only to the right. Specifically, when he is currently on Tile \(j\), he can choose Tile \(j+1\) or Tile \(j+2\) as his next destination. However, he cannot move beyond Tile \(N\) (he can move to Tile \(j+1\) only if \(j+1 \leq N\), and to Tile \(j+2\) only if \(j+2 \leq N\)). Takahashi steps on a tile upon arriving at it. He also steps on Tile \(1\), the starting point. Takahashi ends his movement upon reaching Tile \(N\).
高桥从地砖 \(1\) 出发,地砖 \(N\) 是目标。高桥始终只向右移动。具体来说,当他当前位于地砖 \(j\) 时,他可以选择地砖 \(j+1\) 或地砖 \(j+2\) 作为下一个目的地。但是,他不能移动到地砖 \(N\) 之外(只有当 \(j+1 \leq N\) 时才能移动到地砖 \(j+1\),只有当 \(j+2 \leq N\) 时才能移动到地砖 \(j+2\))。高桥在到达地砖时踩在上面。他也会踩在起点地砖 \(1\) 上。高桥在到达地砖 \(N\) 时结束移动。
Due to the above movement rules, Tile \(1\) and Tile \(N\) are always stepped on. Also, since Takahashi always moves to the right, he never steps on the same tile more than once.
根据上述移动规则,地砖 \(1\) 和地砖 \(N\) 总是会被踩到。此外,由于高桥始终向右移动,他永远不会踩到同一块地砖超过一次。
After Takahashi walks through the corridor, Aoki inspects the corridor and counts the number of tiles with footprints. A footprint is left on Tile \(i\) if the dust thickness on Tile \(i\) after Takahashi's movement is strictly less than the initial thickness \(H_i\).
高桥穿过长廊后,青木检查了长廊,并统计了留有脚印的地砖数量。如果地砖 \(i\) 在高桥移动后的灰尘厚度严格小于初始厚度 \(H_i\),则该地砖上留有脚印。
- If Takahashi did not step on Tile \(i\), the dust thickness remains \(H_i\), so no footprint is left.
如果高桥没有踩到地砖 \(i\),灰尘厚度仍为 \(H_i\),因此不会留下脚印。 - If Takahashi stepped on Tile \(i\), the dust thickness becomes \(\max(0,\; H_i - D_i)\). This is strictly less than \(H_i\) if and only if \(H_i > 0\) and \(D_i > 0\). Therefore, if \(H_i = 0\) or \(D_i = 0\), no footprint is left even if the tile is stepped on.
如果高桥踩到了地砖 \(i\),灰尘厚度变为 \(\max(0,\; H_i - D_i)\)。这严格小于 \(H_i\) 当且仅当 \(H_i > 0\) 且 \(D_i > 0\)。因此,如果 \(H_i = 0\) 或 \(D_i = 0\),即使踩到该地砖也不会留下脚印。
Takahashi wants to minimize the number of tiles with footprints. Find the minimum number of tiles with footprints when Takahashi moves along an optimal path.
高桥希望最小化留有脚印的地砖数量。求高桥沿着最优路径移动时,留有脚印的地砖的最小数量。
【输入】
\(N\)
\(H_1\) \(H_2\) \(\cdots\) \(H_N\)
\(D_1\) \(D_2\) \(\cdots\) \(D_N\)
- The first line contains an integer \(N\), the number of tiles.
- The second line contains \(N\) integers \(H_1, H_2, \ldots, H_N\) separated by spaces, representing the initial dust thickness of each tile.
- The third line contains \(N\) integers \(D_1, D_2, \ldots, D_N\) separated by spaces, representing the upper bound of dust reduction when each tile is stepped on.
【输出】
Print in one line the minimum number of tiles with footprints when Takahashi moves optimally.
【输入样例】
5
3 0 5 2 4
1 1 1 1 1
【输出样例】
3
【核心思想】
-
问题分析:给定 \(N\) 块地砖,每块地砖 \(i\) 有初始灰尘厚度 \(H_i\) 和踩踏减少量 \(D_i\)。高桥从地砖 \(1\) 出发,每次只能向右移动 \(1\) 或 \(2\) 步,最终到达地砖 \(N\)。踩过地砖 \(i\) 后灰尘变为 \(\max(0, H_i - D_i)\),若 \(H_i > 0\) 且 \(D_i > 0\) 则该地砖留下脚印。求最优路径下留下的最少脚印数。这是一个线性 DP 问题,每个位置的状态仅依赖于前两个位置。
-
算法选择:
- 线性 DP(一维递推):
dp[i]表示从地砖 \(1\) 走到地砖 \(i\) 的最小脚印数 - 代价预处理:
cost(i) = 1(当 \(H_i > 0\) 且 \(D_i > 0\)),否则为 \(0\),将原问题转化为带权路径最小代价问题
- 线性 DP(一维递推):
-
关键步骤:
- 初始化:
dp[1] = cost(1)(起点必踩)dp[2] = cost(1) + cost(2)(走到 \(2\) 只有一条路径 \(1 \to 2\))
- 状态转移(对于 \(i = 3, \dots, N\)):
dp[i] = min(dp[i-1], dp[i-2]) + cost(i)- 解释:到达 \(i\) 只能从 \(i-1\) 走 \(1\) 步或从 \(i-2\) 走 \(2\) 步,取两者中脚印数较少的路径,再加上当前地砖的代价
- 输出答案:
dp[N]
- 初始化:
-
时间/空间复杂度:
- 时间复杂度:\(O(N)\),只需一次线性遍历
- 空间复杂度:\(O(N)\),可滚动优化至 \(O(1)\)(只保留前两个状态值)
-
线性 DP 的核心思想:
- 最优子结构:到达位置 \(i\) 的最优解一定由到达 \(i-1\) 或 \(i-2\) 的最优解转移而来
- 有限前驱依赖:本题每次只能走 \(1\) 或 \(2\) 步,因此状态仅依赖前两项,可用滚动数组压缩空间
- 代价抽象:将复杂的脚印判断条件抽象为 \(0/1\) 代价,使问题转化为经典的最小路径和模型
- 适用于路径选择、跳跃游戏、爬楼梯变体等一维序列最优决策问题
【算法标签】
线性DP-一维
【代码详解】
#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
int n; // 数组长度
int h[N], d[N]; // h数组和d数组
int dp[N]; // 动态规划数组
// 计算位置x的代价
int cost(int x)
{
// 如果h[x]和d[x]都大于0,代价为1,否则为0
if (h[x] > 0 && d[x] > 0)
{
return 1;
}
else
{
return 0;
}
}
int main()
{
cin >> n; // 读取数组长度
// 读取h数组
for (int i = 1; i <= n; i++)
{
cin >> h[i];
}
// 读取d数组
for (int i = 1; i <= n; i++)
{
cin >> d[i];
}
// 初始化dp数组为无穷大
memset(dp, 0x3f, sizeof(dp));
// 初始化前两个位置的dp值
dp[1] = cost(1);
dp[2] = cost(1) + cost(2);
// 动态规划转移
for (int i = 3; i <= n; i++)
{
dp[i] = min(dp[i - 1], dp[i - 2]) + cost(i);
}
// 输出结果
cout << dp[n] << endl;
return 0;
}
【运行结果】
5
3 0 5 2 4
1 1 1 1 1
3
浙公网安备 33010602011771号