P2179-[NOI2012]骑行川藏【导数,二分】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P2179


1|1题目大意

给出Ensi,ki,ui求一个序列vi满足

i=1nkisi(viui)2E

的情况下最小化

i=1nsivi

1n104


1|2解题思路

洛谷题解上一个十分神奇的做法看起来。(主要是看不懂拉格朗日乘数法/kk)

首先考虑对于段路的行驶时间ti=sivi,我们可以画出消耗的能量Eti的函数。

对于函数f(E)=ti不难发现的是在viui的情况下E越小这个函数对应位置的导数越小。

也就是消耗单位能量减少的时间也就越少,性价比就越低。而我们现在要给每段路分配一个ti使得消耗能量和等于Eti和最小的话。

根据贪心的思想有选出若干个的ti满足对应位置的导数相等。

那么我们就找到了所有路的共性,考虑二分这个导数,但是我们先对这个函数f(v)=tE求个导。

t=svi2,E=2kisi(viui)

f(v)=tE=s2kisivi2(viui)

然后我们二分出f(vi)=x然后再二分出对应的速度vi就好了。


1|3code

#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=1e4+10; int n;double E,s[N],k[N],v[N]; double getv(double x,int p){ double l=max(v[p],0.0),r=100000; for(int i=1;i<=100;i++){ double V=(l+r)/2.0; if(-2.0*k[p]*V*V*x*(V-v[p])<1.0)l=V; else r=V; } return (l+r)/2.0; } double check(double x){ double E=0; for(int i=1;i<=n;i++){ double V=getv(x,i); E+=k[i]*s[i]*(V-v[i])*(V-v[i]); } return E; } int main() { scanf("%d",&n);scanf("%lf",&E); for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&s[i],&k[i],&v[i]); double l=-1e5,r=0; for(int i=1;i<=100;i++){ double mid=(l+r)/2.0; if(check(mid)<=E)l=mid; else r=mid; } double mid=(l+r)/2.0,ans=0; for(int i=1;i<=n;i++) ans+=s[i]/getv(mid,i); printf("%.12lf\n",ans); return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/14984441.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(39)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 张高兴的大模型开发实战:(一)使用 Selenium 进行网页爬虫
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示