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

ICPC 2023 Nanjing R L 题 Elevator

[ProblemDiscription]\color{blue}{\texttt{[Problem Discription]}}[Problem Discription]

在这里插入图片描述

来源:洛谷。侵权则删。

[Analysis]\color{blue}{\texttt{[Analysis]}}[Analysis]

贪心。优先运送楼层高的货物,在能装下的情况下尽量多装。

因为运送货物的代价仅和最高楼层的货物有关,假设一次运送货物时的最高楼层为 hhh,那么无论你剩下的货物楼层高还是低,代价都是 hhh 是固定的。

既然这样,我们应该优先把尽量高的货物都运送上去,剩下来的都是高度低的货物,后面的代价会减小。

排序后,从楼层高的货物开始装填,能装下就装下。注意处理特殊情况:即电梯剩余空间只有 111,但贪心需要装大小为 222 的货物时是装不下的。但是既然电梯空间还有剩余,就不应该浪费,应该找到下一个大小为 111 的货物。

指针来回的挪动可能会导致 T,因此按 w=1,2w=1,2w=1,2 把货物分成两批,分别用一个指针来维护。这样可以保证时间复杂度为 O(n)O(n)O(n)

总时间复杂度 O(nlog⁡n)O(n \log n)O(nlogn),主要瓶颈在于排序。

但是,并没有做完!

这道题对代码能力的要求还是很高的。代码中有非常多容易出错的地方!相信这个贪心还是很多选手都能想到的,但是能不能写出来也是一个重要的问题。

具体的细节看代码中的注释。

Code\color{blue}{\text{Code}}Code

const int N=1e5+100;struct Marchandise{int amount,high;Marchandise(int a=0,int h=0){amount=a;high=h;}bool operator < (const Marchandise &c) const{return high>c.high;}
}a[N],b[N];//w=1,2 的分别存 int n,r1,r2;
ll lim,ans;int OZDY(){n=read();lim=read();ans=r1=r2=0;for(int i=1;i<=n;i++){int c=read(),w=read(),f=read();if (w==1) a[++r1]=(Marchandise){c,f};else b[++r2]=(Marchandise){c,f};}sort(a+1,a+r1+1);sort(b+1,b+r2+1);a[r1+1]=(Marchandise){0,0};b[r2+1]=(Marchandise){0,0};//没有这两行应该也没问题int l1=1,l2=1;ll remain=lim;while (l1<=r1&&l2<=r2){if (b[l2].high>=a[l1].high&&remain!=1){//楼层高的优先int tmp=(int)min((ll)b[l2].amount,remain>>1);if (remain==lim) ans+=b[l2].high;remain-=(tmp<<1);b[l2].amount-=tmp;//到这一行,remain 和 amount 至少一个被清零。if (!b[l2].amount){l2++;if (remain==0) remain=lim;continue;//注意一定要 continue,不然可能就直接进入下一个 if,开始装填 l2+1 了,但 l2+1 不一定是下一个装填的货物(可能是 l1,但不可能是 l2+2)。}if (l2>r2) break;if (remain==0){ans+=1ll*b[l2].high*((b[l2].amount<<1)/lim);//注意括号b[l2].amount%=(lim>>1);if (!b[l2].amount){l2++;remain=lim;}else{ans+=b[l2].high;remain=lim-(b[l2].amount<<1);l2++;}}}else{if (remain==1){a[l1].amount--;remain=lim;//这句话别忘了if (!a[l1].amount) l1++;continue;}//电梯剩余空间为 1 特殊处理int tmp=(int)min((ll)a[l1].amount,remain);if (remain==lim) ans+=a[l1].high;remain-=tmp;a[l1].amount-=tmp;if (!a[l1].amount){l1++;if (remain==0) remain=lim;//都恰好拿完 continue;}if (l1>r1) break;if (remain==0){ans+=1ll*a[l1].high*(a[l1].amount/lim);a[l1].amount%=lim;if (!a[l1].amount){l1++;remain=lim;}else{ans+=a[l1].high;remain=lim-a[l1].amount;l1++;}}}} //每进入循环一次,要么 l1 加一要么 l2 加一,保证时间复杂度if (remain==0) remain=lim; //注意维护关键变量(其实出循环后 remain 应该不会为 0,但是维护一下以免出乱子,反正不费事)while (l2<=r2){if (remain==1) remain=lim;//只剩下 w=2 的货物了,剩余的 1 空间没用了int tmp=(int)min((ll)b[l2].amount,remain>>1);//下面的语句几乎就是复制过来的。if (remain==lim) ans+=b[l2].high;remain-=(tmp<<1);b[l2].amount-=tmp;if (!b[l2].amount) l2++;//这里不需要 continue 了,因为下一个装的一定是 l2+1if (l2>r2) break;if (remain==0){ans+=1ll*b[l2].high*((b[l2].amount<<1)/lim);b[l2].amount%=(lim>>1);if (!b[l2].amount){l2++;remain=lim;}else{ans+=b[l2].high;remain=lim-(b[l2].amount<<1);l2++;}}}while (l1<=r1){int tmp=(int)min((ll)a[l1].amount,remain);if (remain==lim) ans+=a[l1].high;remain-=tmp;a[l1].amount-=tmp;if (!a[l1].amount) l1++;if (l1>r1) break; if (remain==0){ans+=1ll*a[l1].high*(a[l1].amount/lim);a[l1].amount%=lim;if (!a[l1].amount){l1++;remain=lim;}else{ans+=a[l1].high;remain=lim-a[l1].amount;l1++;}}}//虽然代码看着很长,但是最主要的四段几乎就是复制粘贴,修改一些小细节printf("%lld\n",ans);return n;
}int main(){int T=read();while (T--) OZDY();return 0;
}
http://www.xdnf.cn/news/20271.html

相关文章:

  • 用Android studio运行海外极光推送engagelab安卓的SDK打apk安装包
  • Ribbon和LoadBalance-负载均衡
  • 从Java全栈到前端框架:一次真实面试的深度复盘
  • 验证平台中所有的组件应该派生自UVM中的类
  • 设计艺术~缓存结构设计
  • 【Go项目基建】GORM框架实现SQL校验拦截器(完整源码+详解)
  • C++和OpenGL实现3D游戏编程【连载30】——文字的多行显示
  • MySQL集群——主从复制进阶
  • 2025年上海市星光计划第十一届职业院校技能大赛高职组“信息安全管理与评估”赛项交换部分前6题详解(仅供参考)
  • FlashAttention:突破Transformer内存瓶颈的IO感知革命
  • Web漏洞挖掘篇(二)—信息收集
  • 浪潮CD1000-移动云电脑-RK3528芯片-2+32G-安卓9-2种开启ADB ROOT刷机教程方法
  • Chat with RTX-NVIDIA推出的本地AI聊天机器人
  • .NET Core 应用部署深度解析:从 IIS 到 Docker+Kestrel 的迁移与性能优化实战
  • 电脑音频录制 | 系统麦克混录 / 系统声卡直录 | 方法汇总 / 常见问题
  • Unity与硬件交互终极指南:从Arduino到自定义USB设备
  • 零基础Linux操作基础小白快速掌握Shell脚本--流程控制和循环(二)
  • CAD:注释
  • PPTist,一个完全免费的 AI 生成 PPT 在线网站
  • 贪心算法应用:流行病干预策略问题详解
  • redis的数据类型:Hash
  • 【数据结构】带哨兵位双向循环链表
  • 50系显卡训练深度学习YOLO等算法报错的解决方法
  • 《动手学深度学习v2》学习笔记 | 2.4 微积分 2.5 自动微分
  • 深度学习——PyTorch保存模型与调用模型
  • JUC之并发编程
  • MyBatis入门到精通:CRUD实战指南
  • 使用UniApp实现下拉框和表格组件页面
  • Android Kotlin 动态注册 Broadcast 的完整封装方案
  • uv教程 虚拟环境