1 条题解
-
0
解题思路
问题简述
有 种花,第 种花的花瓣数为 ,数量为 。
现有 枚硬币,每朵花的价格等于其花瓣数(即买一朵花瓣数为 的花需要 枚硬币)。
要求选出的花中,任意两朵花的花瓣数之差不超过 ,问最多能获得的总花瓣数(即总花费,但受限于 ,总花费不能超过 ,且要最大化总花瓣数)。核心思想
由于花瓣数之差不超过 ,因此选出的花只能包含至多两种相邻的花瓣数,设为 和 (也可能只有一种)。
对每个可能的 ,计算在不超过 的前提下,从花瓣数为 和 的花中选出若干朵所能得到的最大总花瓣数,然后取最大值。算法步骤
-
读入并排序
将 配对,按 升序排序。 -
只选一种花
对每种花瓣数 ,若 ,则最多能选 朵,总花瓣数为 。更新答案。 -
同时选两种相邻的花
遍历排序后的列表,对相邻的两种花 和 (两者都存在时)进行如下计算:- 计算最多能选的 花瓣花的数量:
- 剩余硬币:
- 计算最多能选的 花瓣花的数量:
- 此时剩余硬币:
- 尝试将部分已选的 花瓣花替换为 花瓣花:
每替换一朵,总花瓣数增加 ,同时多花 枚硬币。
最多可替换的次数为: - 替换后的总花瓣数为: 用 更新答案。
-
输出答案。
正确性证明
- 只选一种花 的情况显然正确。
- 同时选两种花:
首先,在不超过 的前提下,先尽可能多地选便宜的 花(得到 ),然后在剩余硬币中尽可能多地选 花(得到 ),这是一个可行解。
在此基础上,任何将一朵已选的 花替换为一朵未选的 花的操作,都会使总花瓣数增加 ,同时总花费增加 。只要还有剩余硬币、还有未选中的 花、还有已选中的 花可供替换,就可以执行替换,并且替换不会破坏可行性。
因此,通过贪心地执行替换,可以达到最优解。替换次数的上限由三个因素决定:已选 花的数量 、未选 花的数量 、以及剩余硬币数 。取最小值 即为最多能进行的替换次数,从而得到最优总花瓣数。
由于我们枚举了所有可能的 ,答案一定被包含在内。
复杂度分析
- 排序:
- 遍历并计算:
- 总复杂度:,其中 ,可以轻松通过。
- 空间复杂度:。
代码实现
#include <iostream> #include <vector> #include <algorithm> using namespace std; using ll = long long; void solve() { int n; ll m; cin >> n >> m; vector<pair<ll, ll>> flowers(n); for (int i = 0; i < n; ++i) cin >> flowers[i].first; for (int i = 0; i < n; ++i) cin >> flowers[i].second; sort(flowers.begin(), flowers.end()); ll ans = 0; // 只选一种花 for (int i = 0; i < n; ++i) { ll x = flowers[i].first; ll cnt = flowers[i].second; if (x > m) continue; ll buy = min(cnt, m / x); ans = max(ans, buy * x); } // 同时选两种相邻的花 for (int i = 0; i < n - 1; ++i) { ll x = flowers[i].first; ll cx = flowers[i].second; ll y = flowers[i + 1].first; ll cy = flowers[i + 1].second; if (y != x + 1) continue; // 只处理相邻对 if (x > m) continue; // 计算 k1, k2, remain' ll k1 = min(cx, m / x); ll remain = m - k1 * x; ll k2 = min(cy, remain / y); ll used = k1 * x + k2 * y; ll remain2 = m - used; // 替换次数 r ll r = min({k1, cy - k2, remain2}); ll total = used + r; // 每替换一次总花瓣数增加 1 ans = max(ans, total); } cout << ans << '\n'; } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int t; cin >> t; while (t--) solve(); return 0; } -
- 1
信息
- ID
- 7237
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 2
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者