ACcoders Problem 2048 题解

文章介绍了如何通过数学建模解决一个关于灯泡、墙壁和人影子的问题,首先通过相似三角形建立函数关系式,然后分析当影子全部或部分在地面上时的最大长度,涉及到了分段函数和对勾函数,最后给出了对应的C++代码片段来求解最大值。
摘要由CSDN通过智能技术生成

题意

在这里插入图片描述
有一个灯泡高度为 H H H,它与墙壁的距离为 D D D Mildleopard \text{Mildleopard} Mildleopard 站在灯泡与墙壁之间,身高为 h h h,他与灯光所构成的影长为 L L L,问你 L L L 的最大长度为多少?

思路

我们设 Mildleopard \text{Mildleopard} Mildleopard 与灯泡的位置为 x x x,将影长设为 y y y,求出 x x x y y y 的函数解析式即可求出最值从而求出本题的解。我们考虑分类讨论来得出此问题的答案。

当影子不在墙壁上时


我们很容易就能看出 △ A B C ∼ △ P Q C \triangle ABC\sim \triangle PQC ABCPQC,根据定理,可以得到 A B P Q = B C Q C \displaystyle\frac{AB}{PQ}=\frac{BC}{QC} PQAB=QCBC

再将式子中的线段替换成我们已知的变量,即
H h = x + y y \displaystyle\frac{H}{h}=\frac{x+y}{y} hH=yx+y

然后将其化简
H y = h ( x + y ) Hy=h(x+y) Hy=h(x+y) H y = h x + h y Hy=hx+hy Hy=hx+hy ( H − h ) y = h x (H-h)y=hx (Hh)y=hx

可得出函数解析式,即为
y = h H − h x y=\frac{h}{H-h}x y=Hhhx

但是还需要考虑函数的定义域,因为我们需要保证影子不在墙上,所以 x + y x+y x+y 最多也就只能取到 D D D,即
x + y ≤ D x+y\le D x+yD

可将 Y Y Y 带入,再化简,又得
x + h H − h x ≤ D x+\frac{h}{H-h}x\le D x+HhhxD H H − h x ≤ D \frac{H}{H-h}x\le D HhHxD x ≤ D H − h H x\le D\frac{H-h}{H} xDHHh

则当前情况函数解析式为
y = h H − h x ( 0 ≤ x ≤ D H − h H ) y=\frac{h}{H-h}x(0\le x \le D\frac{H-h}{H}) y=Hhhx(0xDHHh)

当影子有一部分再墙上时

在这里插入图片描述
我们将 y y y 分成了两段,分别是 y 1 y_{1} y1 y 2 y_{2} y2,我们要求的 y y y 即为它们的和。

显而易见, y 2 y_{2} y2 等于 D − x D-x Dx,所以现在只需要算出 y 1 y_{1} y1 也就是 N M NM NM 的长度即可。

在此图中,我们仍可以构建出一个相似三角形, △ A B C ∼ △ P Q C \triangle ABC\sim \triangle PQC ABCPQC,发现此组相似三角形与上一种情况完全相等,可以根据上一情况,得出 C Q = h H − h x \displaystyle CQ=\frac{h}{H-h}x CQ=Hhhx(下列式子中将用 t t t 来代替 h H − h \displaystyle\frac{h}{H-h} Hhh

我们还可以发现,可以再构建出一组相似三角形 △ P Q C ∼ △ N M C \triangle PQC\sim \triangle NMC PQCNMC,又可得到 P Q N M = Q C M C \displaystyle\frac{PQ}{NM}=\frac{QC}{MC} NMPQ=MCQC,再将所有我们已知的变量带入,进行替换,可以得到:
h y 1 = s x s x − y 2 \frac{h}{y_{1}}=\frac{sx}{sx-y_{2}} y1h=sxy2sx

又因 y 2 y_{2} y2 我们已经得出,可直接替换
h y 1 = s x s x − D + x \frac{h}{y_{1}}=\frac{sx}{sx-D+x} y1h=sxD+xsx h y 1 = s x x ( s + 1 ) − D \frac{h}{y_{1}}=\frac{sx}{x(s+1)-D} y1h=x(s+1)Dsx h [ x ( s + 1 ) − D ] = s x × y 1 h[x(s+1)-D]=sx\times y_{1} h[x(s+1)D]=sx×y1 y 2 = h [ x ( s + 1 ) − D ] s x y_{2}=\frac{h[x(s+1)-D]}{sx} y2=sxh[x(s+1)D] y 2 = h × [ x ( s + 1 ) s x − D s x ] y_{2}=h\times[\frac{x(s+1)}{sx}-\frac{D}{sx}] y2=h×[sxx(s+1)sxD] y 2 = h × ( s + 1 s − D s x ) y_{2}=h\times(\frac{s+1}{s}-\frac{D}{sx}) y2=h×(ss+1sxD)

这时,我们可以再将 h H − h \displaystyle\frac{h}{H-h} Hhh 替换回来,即
y 2 = h × ( h H − h + 1 h H − h − D h H − h x ) y_{2}=h\times(\frac{\frac{h}{H-h}+1}{\frac{h}{H-h}}-\frac{D}{\frac{h}{H-h}x}) y2=h×(HhhHhh+1HhhxD) y 2 = h × ( H H − h h H − h − D h H − h x ) y_{2}=h\times(\frac{\frac{H}{H-h}}{\frac{h}{H-h}}-\frac{D}{\frac{h}{H-h}x}) y2=h×(HhhHhHHhhxD) y 2 = h × ( H h − D ( H − h ) h x ) y_{2}=h\times(\frac{H}{h}-\frac{D(H-h)}{hx}) y2=h×(hHhxD(Hh)) y 2 = H − D ( H − h ) x y_{2}=H-\frac{D(H-h)}{x} y2=HxD(Hh)

因为我们求的是 y 1 y_{1} y1 y 2 y_{2} y2 的和,所以需要再加上一个 y 1 y_{1} y1。并且不要忘记加定义域,人离灯泡最远的情况就是已经贴在墙上了,所以上限取到 D D D,下线就是比上一个函数定义域的上限多即可。所以第二种方案的函数解析式即为
y = D − x + H − D ( H − h ) x ( D H − h H ≤ x ≤ D ) y=D-x+H-\frac{D(H-h)}{x}(D\frac{H-h}{H}\le x\le D) y=Dx+HxD(Hh)(DHHhxD)

再将两者结合,构成一个分段函数
y = { h H − h x ( 0 ≤ x ≤ D H − h H ) D − x + H − D ( H − h ) x ( D H − h H ≤ x ≤ D ) y=\begin{cases} \displaystyle\frac{h}{H-h}x(0\le x \le D\frac{H-h}{H}) \\\displaystyle D-x+H-\frac{D(H-h)}{x}(D\frac{H-h}{H}\le x\le D) \end{cases} y= Hhhx(0xDHHh)Dx+HxD(Hh)(DHHhxD)


然后就是取最大值。

取最大值的思路十分明确,取两段分段函数的值,然后再取最大即可。

先看第一个,它是一个正比例函数且单调递增,那么取最大值时, x x x 就应该取 D H − h H \displaystyle D\frac{H-h}{H} DHHh,那最大值即为
y m a x = h H − h × D H − h H = D h H y_{max}=\frac{h}{H-h}\times D\frac{H-h}{H}=\frac{Dh}{H} ymax=Hhh×DHHh=HDh

第二个函数的话我们可以先将其移一下项,可得
y = D + H − [ x + D ( H − h ) x ] y=D+H-[x+\frac{D(H-h)}{x}] y=D+H[x+xD(Hh)]

可以发现,中括号内的式子为一个对勾函数。如果我们要让 y y y 更大,就要让这个对勾函数取最小值。

那要怎么来取呢?这里用均值不等式来简单证一下。

将其套入基本不等式,可得
x + D ( H − h ) x ≥ 2 x D ( H − h ) x x+\frac{D(H-h)}{x}\ge 2\sqrt {x\frac{D(H-h)}{x}} x+xD(Hh)2xxD(Hh) x + D ( H − h ) x ≥ 2 D ( H − h ) x+\frac{D(H-h)}{x}\ge 2\sqrt {D(H-h)} x+xD(Hh)2D(Hh)

当且仅当 x = D ( H − h ) x \displaystyle x=\frac{D(H-h)}{x} x=xD(Hh) 时,等号成立。所以最大值即为 D + H − 2 D ( H − h ) D+H-2\sqrt {D(H-h)} D+H2D(Hh) ,再取两式最大即可。

可这样的话您会 WA \text{WA} WA 的很惨

因为是当且仅当 x = D ( H − h ) x \displaystyle x=\frac{D(H-h)}{x} x=xD(Hh) 时,等号成立,可以取到最大值,但要是如果 D ( H − h ) x \displaystyle\frac{D(H-h)}{x} xD(Hh) 不在 x x x 的取值范围内该怎么办呢?凉拌

我们先将此等式化简一下
x 2 = D ( H − h ) \displaystyle x^{2}=D(H-h) x2=D(Hh) x = D ( H − h ) x=\sqrt{D(H-h)} x=D(Hh)

然后,我们再进行分类讨论。

  • 如果 D ( H − h ) ∈ [ D H − h H , D ] \displaystyle\sqrt{D(H-h)}\in[D\frac{H-h}{H},D] D(Hh) [DHHh,D],那么皆大欢喜, D ( H − h ) \sqrt{D(H-h)} D(Hh) x x x 能取到的范围之内,直接取 D + H − 2 D ( H − h ) D+H-2\sqrt {D(H-h)} D+H2D(Hh)
  • 如果 D ( H − h ) ∈ [ D , ∞ + ) \displaystyle\sqrt{D(H-h)}\in[D,\infty ^{+}) D(Hh) [D,+),说明 x x x 的取值范围在最值 D ( H − h ) \sqrt{D(H-h)} D(Hh) 的左边,因为目前对勾函数左边单调递增,所以 x x x 如果要取最大,一定要取到它的取值范围的右端点,即 y m a x = D + H − [ D + D ( H − h ) D ] = h \displaystyle y_{max}=D+H-[D+\frac{D(H-h)}{D}]=h ymax=D+H[D+DD(Hh)]=h
  • 如果 D ( H − h ) ∈ [ ∞ − , D H − h H ) \displaystyle\sqrt{D(H-h)}\in[\infty ^{-},D\frac{H-h}{H}) D(Hh) [,DHHh),说明 x x x 的取值范围在最值 D ( H − h ) \sqrt{D(H-h)} D(Hh) 的右边,因为目前对勾函数右边单调递减,所以 x x x 如果要取最大,一定要取到它的取值范围的做端点,即 y m a x = D + H − [ D H − h H + D ( H − h ) D H − h H ] = D h H \displaystyle y_{max}=D+H-[D\frac{H-h}{H}+\frac{D(H-h)}{D\frac{H-h}{H}}]=\frac{Dh}{H} ymax=D+H[DHHh+DHHhD(Hh)]=HDh

将其合并成一个分段函数即为
y m a x = { D h H ( D ( H − h ) ≤ D H − h H ) D + H − 2 D ( H − h ) ( D H − h H ≤ D ( H − h ) ≤ D ) h ( D ≤ D ( H − h ) ) y_{max}=\begin{cases}\displaystyle\frac{Dh}{H}(\sqrt{D(H-h)}\le D\frac{H-h}{H}) \\\displaystyle D+H-2\sqrt {D(H-h)}(D\frac{H-h}{H}\le\sqrt{D(H-h)}\le D) \\\displaystyle h(D\le \sqrt{D(H-h)}) \end{cases} ymax= HDh(D(Hh) DHHh)D+H2D(Hh) (DHHhD(Hh) D)h(DD(Hh) )

哪个符合条件就选哪个,最后取两段函数最大值的最大值即可

代码不是很难,按照题目推出来的公式直接照搬即可

#include<bits/stdc++.h>
using namespace std;
double max(double a,double b){return a>b?a:b;}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        double H,h,D;
        scanf("%lf %lf %lf",&H,&h,&D);
        double ans1,ans2;
        ans1=D*h/H;
        if(sqrt(D*(H-h))<=D*((H-h)/H))
            ans2=D*h/H;
        if(D*((H-h)/H)<=sqrt(D*(H-h))&&sqrt(D*(H-h))<=D)    
            ans2=D+H-2*sqrt(D*(H-h));
        if(D<=sqrt(D*(H-h))) ans2=h;
        printf("%.3lf\n",max(ans1,ans2));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值