Problem

在无穷大的水平面上有一个平面直角坐标系,\(N-1\)条垂直于\(x\)轴的直线将空间分为了\(N\)个区域

你被要求把\((0,0)\)处的箱子匀速推到\((x,y)\)

箱子受水平面的摩擦力与正压力正相关,所以在第\(i\)个区域的摩擦力可以表示为\(f_i\)

求把箱子推到目的地做的最小功是多少呢?(不考虑改变速度时的做功)

\(N\leq 100\)

Thoughts

这道题看题面是物理题,但一般来说这些题都是借着物理题的外表掩饰自己的数学本质

以为要从两块区域的简单情形入手,但我发现自己连两块区域都不会做;想到如果所有的\(f_i\)都相等的话,那么只要连一条直线即可,那么想法儿把\(f_i\)化进去,但发现\(\sqrt {x^2+y^2}\)的式子好像没法把\(f_i\)的系数化进去

转念一想,发现箱子肯定在\(f_i\)更大的地方移动得越少,而且在同一块区域内肯定是走直线,所以两块区域中的直线在交界的地方肯定有一个角度偏差,即箱子的整条移动路径是一条折线段

马上可以联想到光在不同介质交界处的折射现象

Physics

既然我们要利用折射计算精确值,那么我们就不能像初中那样仅仅掌握判断入射角和折射角大小关系的方法,我们需要定量计算!

惠更斯原理

惠更斯原理是指球形波面上的每一点(面源)都是一个次级球面波的子波源,子波的波速与频率等于初级波的波速和频率,此后每一时刻的子波波面的包络就是该时刻总的波动的波面。其核心思想是:介质中任一处的波动状态是由各处的波动决定的

看下面几幅图片基本就能理解

(图引自百度)

折射

有了这个原理,我们来证明一个定量的折射定理,如下图

光线在同一时间于\(A,B\)两点处放出子波源,在一个极短的时间\(\Delta t\)内,\(A\)放出的子波源到达\(C\)点,\(B\)放出的子波源到达\(D\),则有

\[\left .
\begin{matrix}
\sin i=\frac {\Delta tv_1}{AD}\\
\sin r=\frac {\Delta tv_2}{AD}\\
\end{matrix}
\right\}\Rightarrow \frac {\sin i}{\sin r}=\frac {v_1}{v_2}
\]

Solution

如何将上面的式子进行应用呢,由于并不是\(f_i\)越大答案越优,所以我们可以取\(v_i=\frac 1{f_i}\),则我们可以得到任意相邻两区间直线斜率的关系:

\[\frac {\sin \theta_1}{\sin \theta_2}=\frac {f_2}{f_1}
\]

但我们并不知道任何区间的斜率,所以我们可以设第一个区间的斜率为\(\theta_0\)(即从原点射出的第一条线段),并且考虑到这条折线在结束横坐标\(x\)的纵坐标\(y_0\)是关于\(\theta_0\)单调递增的,所以我们可以二分\(\theta_0\)来逼近最终我们的期望结束纵坐标\(y\),而我们要求答案的最小值,则我们只有当\(y_0\geq y\)时才能更新答案

……当我们开开心心打完代码,会发现连第二个样例都过不了,交上去只有\(20∽30\)分,问题出在哪了?

容易想到 调试发现 由于我们是以\(\sin \theta\)为途径转移,而途中我们的\(\sin \theta\)可能会出现大于\(1\)的情况,而这种情况的发生是并不是因为发生了全反射,而是我们设的初始值\(\theta_0\)不合法,我们要求\(\forall i\in [1,n],\sin \theta \in [-1,1]\),而\(\sin \theta =\sin \theta_0\frac {f_1}{f_i}\)

所以我们需要设定二分的上界\(\sin \theta_0\leq \frac {\min\{f_i\}}{f1}\),至此此题解决

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rg register
#define pi (3.14159265358979323846) const int N=110;
const double eps=1e-8;
double x[N],f[N];
double ans=1e20,Y;
int n; inline int calc(double theta){
double y=0.0,yy,res=0.0;
theta=sin(theta);
for(rg int i=1;i<=n;++i){
yy=x[i]*tan(asin(theta));
theta*=f[i]/f[i+1];
res+=sqrt(x[i]*x[i]+yy*yy)*f[i];
y+=yy;
}
if(y>Y)
ans=fmin(ans,res);
return y>Y;
} int main(){
scanf("%d",&n);
double l=0.0,r=pi*0.5,m,mi=1e20;
for(rg int i=1;i<=n;++i){
scanf("%lf%lf",&x[i],&f[i]);
if(i^1)mi=fmin(mi,f[i]);
}
scanf("%lf",&Y);
r=min(r,asin(mi/f[1]));
while(l+eps<r){
m=(l+r)*0.5;
if(calc(m))r=m;
else l=m;
}printf("%.3lf\n",ans);
return 0;
}

题解-拉格朗日(bzoj3695变种)的更多相关文章

  1. BZOJ2876 [Noi2012]骑行川藏 【拉格朗日乘数法】

    题目链接 BZOJ 题解 拉格朗日乘数法 拉格朗日乘数法用以求多元函数在约束下的极值 我们设多元函数\(f(x_1,x_2,x_3,\dots,x_n)\) 以及限制\(g(x_1,x_2,x_3,\ ...

  2. 【BZOJ】2876: [Noi2012]骑行川藏

    题意 给出\(s_i, k_i, v_i', E\),满足\(\sum_{i=1}^{n} k_i s_i ( v_i - v_i' )^2 \le E, v_i > v_i'\),最小化$ \ ...

  3. BZOJ2287: 【POJ Challenge】消失之物

    2287: [POJ Challenge]消失之物 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 254  Solved: 140[Submit][S ...

  4. 题解 P4781 【【模板】拉格朗日插值】

    题目 本蒟蒻看到一道数学题,就顺手切了.感觉单单对这一题而言,部分评论区的大佬过于复杂了 [分析] 先讲讲拉格朗日插值法: 对于给定的 \((n+1)\) 个点,我们可以确定唯一的一个 至多\(n\) ...

  5. 【LeetCode题解】二叉树的遍历

    我准备开始一个新系列[LeetCode题解],用来记录刷LeetCode题,顺便复习一下数据结构与算法. 1. 二叉树 二叉树(binary tree)是一种极为普遍的数据结构,树的每一个节点最多只有 ...

  6. 【LeetCode题解】数组Array

    1. 数组 直观地看,数组(Array)为一个二元组<index, value>的集合--对于每一个index,都有一个value与之对应.C语言中,以"连续的存储单元" ...

  7. 华南师大 2017 年 ACM 程序设计竞赛新生初赛题解

    题解 被你们虐了千百遍的题目和 OJ 也很累的,也想要休息,所以你们别想了,行行好放过它们,我们来看题解吧... A. 诡异的计数法 Description cgy 太喜欢质数了以至于他计数也需要用质 ...

  8. bzoj2876 [NOI2012]骑行川藏(拉格朗日乘数法)

    题目描述 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因此在每天的骑行 ...

  9. 【CSA35G】【XSY3318】Counting Quests DP 拉格朗日反演 NTT

    题目大意 zjt 是个神仙. 一天,zjt 正在和 yww 玩猜数游戏. zjt 先想一个 \([1,n]\) 之间的整数 \(x\),然后 yww 开始向他问问题. yww 每次给 zjt 一个区间 ...

随机推荐

  1. java中变量关系

  2. Android adb shell 常用命令

    Ø  简介 adb 命令是 Android SDK 中自带的一个调试工具,可以调试电脑中的手机或者模拟器,使用 adb 命令前需要将 sdk 中的 platform-tools 目录添加到环境变量中. ...

  3. XXE攻防

    一.XML基础知识 XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言.XML文档结构包括XML声明.DTD文档类型定义(可 ...

  4. springboot10-springcloud-eureka 服务注册与发现,负载均衡客户端(ribbon,feign)调用

    创建5个项目: 1.服务注册中心 2.服务提供者1 3.服务提供者2(与服务提供者1的代码实现一样,这是是为了模拟负载均衡) 4.ribbon客户端项目 5.feign客户端项目 如图: 一.注册中心 ...

  5. 20155324 2016-2017-2 《Java程序设计》第十周学习总结

    20155324 2016-2017-2 <Java程序设计>第十周学习总结 教材学习内容总结 Java的网络编程 网络编程 网络编程就是在两个或两个以上的设备(例如计算机)之间传输数据. ...

  6. MyList 泛型委托

    using System; using System.Collections; using System.Collections.Generic; using System.Linq; using S ...

  7. Zipkin 分布式数据追踪系统

    Zipkin 是一个分布式数据追踪系统,适用于微服务架构下的调用链路数据采集及分析工作. 可通过一个 Web 前端轻松的收集和分析数据,例如用户每次请求服务的处理时间等,可方便的监测系统中存在的瓶颈. ...

  8. 关于mirai的一些研究

    关于mirai的一些研究 0x01.源码编译: 配置好对应的go开发环境,即可进行编译,生成了主要的文件 badbot为僵尸节点的可执行文件,cnc为主控端的可执行文件,其它一些为辅助工具. 如下图所 ...

  9. SpringBoot学习笔记<一>入门与基本配置

    毕业实习项目技术学习笔记 参考文献 学习视频 2小时学会Spring Boot:https://www.imooc.com/learn/767 学习资料 SpringBoot入门:https://bl ...

  10. c++ virtual 记录

    虚继承: http://zh.wikipedia.org/wiki/%E8%99%9A%E7%BB%A7%E6%89%BF 解决了菱形继承问题 cB cC 继承cA    cD继承cB,cC    c ...