1 条题解
-
0
题意翻译
有一个长度为 的数组 ,其中 , 表示晴天, 表示雨天。
一次登山需要连续 个晴天(即连续 个 )。每次登山结束后,必须至少休息一天(即不能连续两天开始新的登山)。
求最多能进行多少次登山。关键观察
- 只有连续的一段晴天(称为一个“晴天块”)才可能进行登山。
- 在一个长度为 的晴天块中,每次登山占用 个晴天,并且两次登山之间必须至少间隔 天(可以是晴天或雨天,但因为是同一个块内,所以只能是晴天)。因此,除了最后一次登山外,每次登山后面都要跟一个休息日。
- 因此,进行 次登山需要的总天数至少为: 这个值必须 ,即
- 由于 是整数,一个块内最多能进行的登山次数为
算法步骤
- 读入 组测试数据。
- 对每组数据:
- 读入 和数组 。
- 扫描数组,找出所有连续的 的长度。
- 对每个长度 ,累加 到答案。
- 输出答案。
复杂度分析
- 只需一次 扫描,空间 。
- 所有测试用例的总 不超过 ,因此总复杂度 。
代码实现(C++)
#include <bits/stdc++.h> using namespace std; void solve() { int n, k; cin >> n >> k; vector<int> a(n); for (int i = 0; i < n; ++i) cin >> a[i]; int ans = 0; int len = 0; for (int i = 0; i < n; ++i) { if (a[i] == 0) { len++; } else { if (len > 0) { ans += (len + 1) / (k + 1); len = 0; } } } if (len > 0) ans += (len + 1) / (k + 1); cout << ans << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; }正确性说明
- 每个晴天块独立,因为雨天天然提供了休息日,且不同块之间的间隔至少为 (雨天),所以不会互相影响。
- 在一个块内,最优策略就是尽可能紧凑地安排登山:每次登山后紧跟一个休息日(除了最后一次),这样能最大化次数。公式 正是这种紧凑安排下可得到的最大次数。
- 反证法:若存在一种安排得到 次登山,则必然满足 ,所以 ,因此 不会超过公式值。而构造法:将块视为 个位置(末尾虚拟一个休息日),然后每 个位置分配一次登山(前 个为登山,第 个为休息),即可达到公式值。因此公式是最优的。
示例验证
- 样例1:
块长度: → ; → ;总和 ,输出 。 - 样例2:全 ,
块长度 → ,输出 。 - 样例3:全 ,无块 → 。
- 样例4:
两个块长度均为 → ,总和 。 - 样例5:
块长度 → ;块长度 → ;总和 ,输出 。
全部匹配示例输出。
- 1
信息
- ID
- 6642
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 6
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者