T799 地道
原题:(权限限制没有超链接)
题目背景
在战争当中,B 国为了抵御 A 国的侵略,广泛使用着地道战的战术。
题目描述
在一 片山地上,下列红色标注的地道是必须要建造的:
按上图建立平面直角坐标系。
现在可能在(w,h)到(0,0)的线段上还要选择一个位置垂直向下挖通达到红色的地道。
所有地道均需要开挖,不允许挖非地道的部分。人从斜边上开始下挖,土石全部要运到斜边上,每p单位长度的土石(忽略截面积)整体运距离 d(无论垂直还是水平)均需付出 p*d 的代价。注意开挖与外运的道路都必须畅通(即要从已经挖好的道路运出)。
试确定这个新地道的 x 坐标,以使开挖地道所需的代价最小。
输入输出格式
输入格式:
第一行三个整数 w,h,op。
op为0表示只修建红色地道,op为1表示还要新修建一条地道。
输出格式:
第一行输出最小的开挖代价;
若op=1则第二行输出新地道 x 坐标。
答案正确当且仅当你的输出与标准输出的差距不超过10^-6;
输入输出样例
输入样例#1:
8 4 1
输出样例#1:
31.500000
3.000000
说明
先挖新隧道和红色隧道的(3,0)到(0,0)部分,一半土从竖直隧道运出,一半从水平隧道运出。
挖剩余红色隧道时,从(6.75,0)往左的土从竖直隧道中运出,其余的从新隧道运出。
对于 30%的数据,op=0;
对于100%的数据,op∈{0,1},0<h<w<=100000;
个人解法:
首先,对于长度为len的一段土,搬运到外面的花费应该是sqr(len)/2(用微积分的思想很容易想出来)。
接下来我们又可以简单地证明出来,对于一段左右均有出口的长度为len的土段,最小花费为sqr(len)/4(用二次函数的思想可以很容易想出),此时以len/2的位置为分界,左右两端分别向不同的方向运出。
所以对于op=0时,我们就可以得出公式了。
为了方便表示,我们把这样运出len的土定义为一次操作。
那么如果中间仍需修一条地道,我们同样可以用这样一个公式。将地道连同地道左边的所有土做一次操作。对于地道连同右边的土再做一次操作。二者相加之后,我们发现把地道的土算了两遍,因此再减去地道的土出去的费用。
这样便是最小花费。
我们可以计算出花费w与x(如图)的关系——同样是一个二次函数。因此求出最值即可。
有一个提醒点:如果w,h,op是用longint储存,那么在运算中可能会超出longint从而出现负数。因此建议都用double储存。
代码如下:
var
len,ans,a,b,c,x,w,h,op:double;
function f(x:double):double;
begin
exit(a*sqr(x)+b*x+c);
end;
begin
read(w,h,op);
if op=0 then
begin
len:=w+h;
ans:=sqr(len)/4;
writeln(ans:0:6);
end
else
begin
a:=((sqr(h/w+1)/4)-(sqr(h/w)/2)+(sqr(h/w-1)/4));
b:=(h+w)*(h/w-1)/2;
c:=sqr(h+w)/4;
x:=-b/(2*a);
ans:=f(x);
writeln(ans:0:6);
end;
if op=1 then writeln(x:0:6);
end.
某位出题人说“我们要是连这道题都做不出来初中数学就是体育老师教的……”然而似乎……也要看懂题啊!!!!
看来自己还是蒟蒻了些呢……