当前位置: 首页 > news >正文

Luogu P6893 [ICPC 2014 WF] Buffed Buffet 题解

01背包不可以贪心,但是分数背包可以。

分别考虑两种物品然后枚举合并。

对于 D 类食物,令 \(f(i, j)\) 表示前 \(i\) 种菜吃了 \(j\)​ 克时的最大美味值:

\[\begin{aligned} f(i, j) &= \max_{0 \leq k \leq \lfloor \frac{j}{w_i} \rfloor} \left( f(i - 1, j - kw_i) + \sum_{n = 1}^{k}(t_i - (n - 1) \Delta t_i) \right) \\ f(i, j) &= \max_{0 \leq k \leq \lfloor \frac{j}{w_i} \rfloor} \left( f(i - 1, j - kw_i) + kt_i - \frac{\Delta x_i \times k(k - 1)}{2} \right) \end{aligned} \]

注意到 \(i\) 这一维可以压缩掉,处理第 \(i\) 种菜时令 \(g(i)\) 表示前 \(i - 1\) 个物品的结果,算完第 \(i\) 个物品之后更新到 \(f\) 上去就可以。也就是说,对于单个物品 \((w, t, \Delta t)\),转移化简为:

\[f(j) = \max_{0 \leq k \leq \lfloor \frac{j}{w} \rfloor} \left( g(j - kw) + kt - \frac{\Delta t \cdot k(k - 1)}{2} \right) \]

考虑怎么搞掉这个除法下取整,按同余类来分离,将下标按照除以 \(w\) 的余数分类处理。

\(j = j'w + r\),其中 \(0 \leq r \lt w\),则 \(j - kw = (j' - k)w + r\),设 \(i = j' - k\),则有:

\[f(j'w + r) = \max_{0 \leq i \leq j'} \left( g(iw + r) + (j' - i)t - \frac{\Delta t \cdot (j' - i)(j' - i - 1)}{2} \right) \]

展开上面这个式子,重新整理:

\[\begin{aligned} f(j'w + r) &= \max_{i} \left( g(iw + r) + (j' - i)t - \frac{\Delta t}{2}({j'}^2 - 2ij' - j' + i) \right) \\ &= \max_{i} \left( g(iw + r) - it - \frac{\Delta t}{2} i(i + 1) + \Delta t i j' \right) + j't - \frac{\Delta t}{2} j'(j' - 1) \end{aligned} \]

注意到后面抽离出来的东西和 \(i\) 无关,考虑对这个 \(f\) 构造点和斜率,令 \(X(i) = i, Y(i) = g(iw + r) - it - \frac{\Delta t}{2} i(i + 1)\),有:

\[f(j'w + r) = \max_{i} (Y(i) - (-\Delta t j') \times X(i)) + R \]

其中 \(R\) 为无关 \(i\) 常数,这等价于在平面的点 \((X(i), Y(i))\) 中找到使得直线 \(y = kx + b\) 的截距 \(b\) 最大的点,其中斜率 \(k = -\Delta t j'\),由于 \(\Delta t \gt 0\)\(j'\) 递增,\(k\) 递增,单调队列维护凸包。每个决策点 \(i\) 对应点 \((i, Y(i))\),随着 \(j'\) 增大 \(k\) 会负得越来越多越来越陡,最优决策点在凸包上移动。复杂度降到了 \(O(w)\)

考虑对 C 类食品的贪心。每次取当前收益最大的,当两种物品的收益 \(x, y\) 相等时考虑合并得到收益为 \(\frac{1}{\frac{1}{x} + \frac{1}{y}}\),这一部分的复杂度为 \(O(d + w)\)

上面说到的枚举合并指的是枚举划分多少给 C 类剩下的给 B 类。

#include <bits/stdc++.h>using i64 = long long;struct C {int t, dt;
};struct D {int w, t, dt;
};bool inline operator<(const C& a, const C& b) {return a.t > b.t;
}int d, w;
int cc, dc;
std::vector<C> fc;
std::vector<D> fd;namespace Sol1 {int ct, cd, cw, r;std::vector<double> f, g;std::deque<int> q;double x(int p) {return p;}double y(int p) {return g[p * cw + r] - p * ct - 0.5 * cd * p * (p + 1);}double slope(int l, int r) {double lx = x(l), rx = x(r), ly = y(l), ry = y(r);return (ry - ly) / (rx - lx == 0 ? 1e-10 : rx - lx);}void ins(int p) {while (q.size() > 1 && slope(q[q.size() - 2], q.back()) < slope(q[q.size() - 2], p)) q.pop_back();q.push_back(p);}void del(double k) {while (q.size() > 1 && slope(q.front(), q[1]) > k) q.pop_front();}void add(int wi, int t, int dt) {cw = wi, ct = t, cd = dt;for (int i = 1; i <= w; i++) {g[i] = f[i];f[i] = -1e18;}for (r = 0; r < cw; r++) {q.clear();for (int j = 0; j * cw + r <= w; j++) {ins(j);del(-dt * j);int i = q.front();f[j * cw + r] = std::max(f[j * cw + r], g[i * cw + r] + (j - i) * t - 0.5 * (j - i) * (j - i - 1) * dt);}}}void calc() {f.assign(w + 1, -1e18);g.resize(w + 1);for (int i = 1; i <= dc; i++) add(fd[i].w, fd[i].t, fd[i].dt);}
}namespace Sol2 {std::vector<double> f;void calc() {f.resize(w + 1);if (cc == 0) {for (int i = 1; i <= w; i++) f[i] = -1e18;return;}std::sort(fc.begin() + 1, fc.begin() + cc + 1);int p = 1;double cur = fc[1].t, cdt = fc[1].dt, cw = 0, sum = 0;p++;for (int i = 1; i <= w; i++) {while (cw < i) {if (p > cc || cur - cdt * (i - cw) > fc[p].t) {sum += cur * (i - cw) - 0.5 * (i - cw) * (i - cw) * cdt;cur -= cdt * (i - cw), cw = i;} else {double q = (cur - fc[p].t) / cdt;sum += cur * q - 0.5 * q * q * cdt;cur = fc[p].t, cw += q;cdt = 1.0 / (1.0 / cdt + 1.0 / (fc[p].dt != 0 ? fc[p].dt : 1e-10));p++;}}f[i] = sum;}}
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cin >> d >> w;fc.resize(d + 1);fd.resize(d + 1);while (d--) {char tp[10];std::cin >> tp;if (tp[0] == 'D') {++dc;std::cin >> fd[dc].w >> fd[dc].t >> fd[dc].dt;} else {++cc;std::cin >> fc[cc].t >> fc[cc].dt;}}Sol1::calc();Sol2::calc();double ans = -1e18;for (int i = 0; i <= w; i++) ans = std::max(ans, Sol2::f[i] + Sol1::f[w - i]);if (cc == 0 && ans < -1e16) std::cout << "impossible\n";else std::cout << std::fixed << std::setprecision(10) << ans << "\n";return 0;
}
http://www.jsqmd.com/news/46797/

相关文章:

  • 苏州一对一辅导机构哪家好?2026实测排行榜,这5家值得重点关注!
  • 性能优化 | HarmonyOS预加载,三步即可提升APP页面的响应速度
  • CF1437F Emotional Fishermen
  • 习题解析之:汽车限行
  • 立贴明志
  • 石墨文档怎么批量导出?我自己手搓了一个 Chrome 插件(附下载)
  • 量子力学作业6
  • 【LVGL】选项卡部件
  • python学习-print
  • WSL2调用摄像头并使用OpenCV - 教程
  • unity动态将3d标牌UI加载到模型子物体下,UI变形问题
  • 2025湛江一对一辅导机构测评榜:从城区到县域的靠谱补习方案全解析
  • 常州一对一家教机构哪个好?2026权威测评榜单:从师资到提分,5家主流平台深度对比
  • 二次验证码介绍及使用
  • 2025汕头一对一家教机构口碑排名:从小学到高中,权威测评5家靠谱机构,实用方案覆盖金平龙湖等全区域
  • Veeam Data Platform 13.0 发布 - 数据保护和管理解决方案
  • 2025年7大AI写论文工具推荐|一键生成+文献智能整合,毕业论文查重无忧!
  • 国标GB28181算法算力平台EasyGBS如何为养老院构建全天候安全防线?
  • 江苏省做合同纠纷比较靠谱的律所推荐及选择参考
  • 如何结合langchain、neo4j搭建关联检索问答
  • 2025年四川科技展馆设计公司权威推荐榜单:科技展厅设计/科技展览设计/城市规划馆设计源头公司精选
  • 江苏省婚姻家庭纠纷律所推荐:专业法律服务机构盘点
  • 携手哲讯,以智慧赋能,驾驭数字未来——您值得信赖的SAP本土化专家
  • 2025中山一对一辅导机构权威测评榜!家教培训平台口碑实测总结报告
  • 学习率对于PPO训练的作用
  • 佛山一对一家教机构哪家好?2025 最新口碑测评与高性价比推荐指南
  • 徐州一对一辅导机构哪个好?2026最新家教平台TOP5权威测评!精准提分数据溯源
  • 微波烘干设备适用物料及工业应用场景解析
  • 微波烘干设备操作流程及相关设备应用解析
  • 2025 最新推荐碳纤木门厂家口碑排行榜:PUR 无缝封边 + 45 磁吸静音技术领衔,环保无甲醛优质企业全解析耐磨防刮/环保无甲醛/防污易清洁/耐腐蚀/铝/LVL 龙骨/复合碳纤木门公司推荐