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

【洛谷P1417】烹调方案 题解

题目大意

一共有 nnn 件食材,每件食材有三个属性,aia_iaibib_ibicic_ici,如果在 ttt 时刻完成第 iii 样食材则得到 ai−t×bia_i-t\times b_iait×bi 的美味指数,用第 iii 件食材做饭要花去 cic_ici 的时间。
需要设计烹调方案使得在TTT的时间内美味指数最大并输出。

数据范围及约定

  • 对于 40%40\%40% 的数据 1≤n≤101 \le n \le 101n10
  • 对于 100%100\%100% 的数据 1≤n≤501 \le n \le 501n50

所有数字均小于 10510^5105

暴力想法

首先我们可以观察到,若不考虑烹饪顺序,或是已知顺序的情况下,求解是很简单的:只需要使用复杂度O(n^2)的01背包进行dp即可

(如果不知道01背包,强烈建议跳转主页学习)

注意到前40%数据的N很小,我们便可以直接暴力枚举菜品的全排列,进行dp即可。

想明白后,我们稍加计算,就会发现:

超时辣!

时间复杂度O(n22n)O(n^22^n)O(n22n)过不了哒!(理论上超3e8次运算,数据很水就当我没说)

正解

其实刚刚的想法已经比较接近正解了。我们来看看上面的做法能怎么优化。

对于后半部分,可以基本确定是没有优化空间的——首先dp是必做,其次就算能将dp优化到O(nlogn)O(nlogn)O(nlogn)甚至O(n)O(n)O(n),大数据依旧是过不了的。

于是我们考虑如何排列烹饪顺序

首先可以观察到一个性质:如果交换相邻两个菜品的烹饪顺序,对前后菜品产生的贡献是没有影响的,因为交换后此前烹饪的总时间不变!

也就是说,如果存在菜品A优于B(即先烹饪A价值更大)、B优于C,则一定有A优于C!

接下来我们开始推理每种菜品的应有顺序。

假设有两个相邻的菜品序号为 i,ji,ji,j ,之前所用的总时间为TTT

根据题意可得,若先烹饪iii号菜品,得到的价值一共是:

w1=(ai−bi×(T+ci))+(aj−bj×(T+ci+cj))w_1=(a_i-b_i×(T+c_i))+(a_j-b_j×(T+c_i+c_j))w1=(aibi×(T+ci))+(ajbj×(T+ci+cj))
=ai+aj−T×(bi+bj)−bi×ci−bj×ci−bj×cj=a_i+a_j-T×(b_i+b_j)-b_i×c_i-b_j×c_i-b_j×c_j=ai+ajT×(bi+bj)bi×cibj×cibj×cj

若先烹饪jjj号菜品,得到的价值一共是:

w2=(aj−bj×(T+cj))+(ai−bi×(T+cj+ci))w_2=(a_j-b_j×(T+c_j))+(a_i-b_i×(T+c_j+c_i))w2=(ajbj×(T+cj))+(aibi×(T+cj+ci))
=ai+aj−T×(bi+bj)−bi×ci−bi×cj−bj×cj=a_i+a_j-T×(b_i+b_j)-b_i×c_i-b_i×c_j-b_j×c_j=ai+ajT×(bi+bj)bi×cibi×cjbj×cj

显然,若先烹饪iii号更优,则有w1>w2w_1>w_2w1>w2

带入并化简两边,可以得到 −bj×ci>−bi×ci-b_j×c_i>-b_i×c_ibj×ci>bi×ci

即:若bj×ci<bi×cjb_j×c_i<b_i×c_jbj×ci<bi×cj,则先烹饪iii号菜品更优。

所以,我们可以先根据上述结论对数组排序,再做dp

时间复杂度O(nT)O(nT)O(nT)(毕竟nnn很小,排序时间可以不计)

AC代码

#include<bits/stdc++.h>
using namespace std;
#define For(i, j, k) for(int i = j; i <= k; i++)
#define dFor(i, j, k)for(int i = j; i >= k; i--)
#define MaxN 55
#define int long longstruct Node{int a, b, c;bool operator<(const Node x) const{		//重载运算符,按之前的结论排序return c * x.b < b * x.c;}
}a[MaxN];
int T, n;
int f[MaxN][100005];signed main()
{cin >> T >> n;For(i, 1, n) cin >> a[i].a;For(i, 1, n) cin >> a[i].b;For(i, 1, n) cin >> a[i].c;sort(a+1, a+n+1);int ans = 0;For(i, 1, n){For(j, 1, T){				//01背包,虽然没有降维优化awaf[i][j] = max(f[i][j], f[i-1][j]);if(j >= a[i].c){f[i][j] = max(f[i][j], f[i-1][j-a[i].c] + a[i].a-a[i].b*j);}ans = max(ans, f[i][j]);}}cout << ans << endl;return 0;
}

总结

思维难度相对较高,主要在于推理传递性和排序规则

类似的题目还有P1060国王游戏等,可以练习

最后,制作实在不易。如果你喜欢这篇文章,可以点个免费的关注和免费的赞

我们下期再见!

http://www.dtcms.com/a/286459.html

相关文章:

  • ONNX模型使用指南:从零开始掌握跨领域模型部署
  • 图片平铺下去总是有个缝隙的解决方案
  • 塞舌尔公司的查册报告Certificate of Official Search是什么?有什么信息
  • 瀚高数据库开启Oracle兼容模块
  • vue2 面试题及详细答案150道(101 - 120)
  • ubuntu20.04使用unity3d做机器人仿真环境搭建
  • Python单例模式详解:从原理到实战的完整指南
  • 详解Linux(Ubuntu/RedHat/CentOS)及国产服务器统一加域管理方案
  • GoC 上册课程
  • java+vue+SpringBoot集团门户网站(程序+数据库+报告+部署教程+答辩指导)
  • docker--程序自启动
  • HIMA X-DO3201模块的冗余配置方法
  • Python Pandas 实践学习笔记(1)
  • Chainlit + FasiAPI+ LlamaIndex 实现RAG(一)
  • 深入解析:短连接 vs 长连接 vs 短轮询 vs 长轮询
  • keil5使用技巧----keil-build-viewer.exe插件使用
  • 前端性能优化“核武器”:新一代图片格式(AVIF/WebP)与自动化优化流程实战
  • Ubuntu查看Docker容器
  • React智能Tooltip封装术:精准检测文本溢出,告别无效提示!
  • Linux下使用原始socket收发数据包
  • 4644电源管理芯片在微波射频组件中的技术优势与国产化实践
  • 《5分钟开发订单微服务!飞算JavaAI实战:IDEA插件安装→空指针修复→K8s部署全流程》
  • 高并发、高性能、高可用
  • LeetCode热题100【第4天】
  • openinstall九周年:聚焦安全防御,护航业务持续增长
  • 40+个常用的Linux指令——上
  • 【ACL系列论文写作指北19-科研中角色定位与自我认知】-如何在一篇论文中摆正自己的位置
  • 由于热爱,我选PGCE专家学习
  • 自动化测试面试中常见的问题
  • 从碎片设备到全球算力:Sollong引领AI时代的基础资源革命