整体思路
此问题可使用动态规划来解决,核心在于算出在给定的总时间 k
内,游览各个景点所消耗的时间,接着通过状态转移方程更新在每个时间点下所能游览的最多景点数,最终得到在总时间 k
内最多可游览的景点数量。
代码详细解释
1. 变量定义与初始化
#include <iostream>
#include <algorithm>
using namespace std;
const int MAXN = 1010;
const int MAXK = 100100;
int pos[MAXN];
int ti[MAXN];
int f[MAXK];
int d[MAXN];
MAXN
和MAXK
分别代表景点数量与总时间的上限。pos
数组用于存放每个景点在数轴上的位置。ti
数组用于存放游览每个景点所需的时间。f
数组为动态规划数组,f[j]
表示在时间j
内最多能游览的景点数。d
数组用于存放相邻两个景点之间的移动时间。
2. 输入处理
int n, k;
cin >> n >> k;
cin >> pos[1] >> ti[1];
d[1] = pos[1];
for (int i = 2; i <= n; i++) {
cin >> pos[i] >> ti[i];
d[i] = pos[i] - pos[i - 1];
}
- 读取景点数量
n
和总游览时间k
。 - 读取第一个景点的位置
pos[1]
和游览时间ti[1]
,因为从 0 出发,所以到达第一个景点的移动时间d[1]
就是其位置。 - 借助循环读取剩余
n - 1
个景点的位置和游览时间,同时算出相邻两个景点之间的移动时间d[i]
。
3. 动态规划过程
for (int i = 1; i <= n; i++) {
int tt = d[i];
int t = tt + ti[i];
if (t > k) continue;
for (int j = k; j >= t; j--) {
f[j] = max(f[j], f[j - t] + 1);
}
}
- 外层循环逐个遍历景点。
- 针对每个景点,计算到达该景点并游览所需的总时间
t
,也就是移动时间d[i]
与游览时间ti[i]
之和。 - 若总时间
t
超出了给定的总游览时间k
,则跳过该景点。 - 内层循环从总时间
k
开始倒序遍历到t
,对于每个时间j
,更新f[j]
的值为f[j]
和f[j - t] + 1
中的较大值。这里的状态转移方程f[j] = max(f[j], f[j - t] + 1)
表示在时间j
内,要么不游览该景点(f[j]
),要么游览该景点(f[j - t] + 1
)。
4. 输出结果
cout << f[k];
最终输出在总时间 k
内最多能游览的景点数量 f[k]
。
复杂度分析
- 时间复杂度:
O
(
n
∗
k
)
O(n * k)
O(n∗k),其中
n
为景点数量,k
为总游览时间。这是因为有两层嵌套循环,外层循环遍历n
个景点,内层循环遍历k
个时间点。 - 空间复杂度:
O
(
k
)
O(k)
O(k),主要用于存储动态规划数组
f
。