题解:P14635 [NOIP2025] 糖果店 / candy(民间数据)
lin_A_chu_K_fan · · 题解
糖果购买问题 题解
题目背景
小 R 有 m 元钱,要在 n 种糖果中购买尽可能多的糖果。每种糖果的购买价格是周期变化的。
题目分析
对于第 i 种糖果:
- 第奇数颗价格为
x_i 元 - 第偶数颗价格为
y_i 元 购买模式:x_i, y_i, x_i, y_i, \ldots
解题思路
省流:贪心。
关键观察
- 每两颗糖果的花费固定:任意连续两颗糖果总花费为
x_i + y_i 元 - 贪心策略:优先选择平均价格低的糖果批量购买
算法步骤
- 计算所有糖果的
sum_i = x_i + y_i - 按
sum_i 从小到大排序 - 尽量购买"两颗一组"的组合
- 用剩余的钱优化购买:
- 买一颗新糖果(选最小
x_i ) - 替换策略:用更便宜的单颗换掉贵的组合
- 买一颗新糖果(选最小
代码实现
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
int main() {
int n;
ll m;
cin >> n >> m;
vector<ll> x(n), y(n), sum(n);
ll min_x = 1e18, min_y = 1e18;
for (int i = 0; i < n; i++) {
cin >> x[i] >> y[i];
sum[i] = x[i] + y[i];
min_x = min(min_x, x[i]);
min_y = min(min_y, y[i]);
}
sort(sum.begin(), sum.end());
ll ans = 0;
ll cost = 0;
// 批量购买两颗一组的组合
for (int i = 0; i < n; i++) {
if (cost + sum[i] <= m) {
cost += sum[i];
ans += 2;
} else {
break;
}
}
ll remaining = m - cost;
// 情况1:买一颗新的糖果
if (remaining >= min_x) {
ans = max(ans,ans + 1);
}
// 情况2:替换策略
if (ans >= 2) {
ll new_remaining = remaining + sum[ans/2 - 1] - min_y;
if (new_remaining >= min_x) {
ans = max(ans, ans - 2 + 3);
}
}
// 情况3:钱太少
if (min_x > m && min_y > m) {
ans = 0;
}
cout << ans << endl;
return 0;
}
警告:代码中含有防抄袭改动,请勿直接复制!!