题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2241
中文题目,不解释
解题思路:
对于每个折线区间,Y+F之和必然是一个凹函数,求导就知道。
对于每段折线进行三分求极值,然后取所有段极值的最小值,即可得到最后解。
源代码:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<algorithm>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const double eps=1e-6;
LL N;
int M;
struct node
{
double x,y;
}p[10005];
double f(double x)
{
return N/x/x;
}
double cal(int key) //在区间k中通过三分求取最小影响
{
double k,b; //y函数的系数
double lx,ly,rx,ry;
double ll,rr;
double x;
lx=p[key].x; ly=p[key].y;
rx=p[key+1].x; ry=p[key+1].y;
k=(ry-ly)/(rx-lx);
b=ly-k*lx;
while(rx-lx>eps)
{
ll=lx+(rx-lx)*0.382;
rr=lx+(rx-lx)*0.618;
if(f(ll)+k*ll>f(rr)+k*rr)
lx=ll;
else
rx=rr;
}
return min(f(lx)+lx*k,f(rx)+rx*k)+b;
}
int main()
{
freopen("in.txt","r",stdin);
int i;
int l,r,ll,rr;
double ans;
while(scanf("%d%I64d",&M,&N)==2)
{
memset(p,0,sizeof(p));
for(i=1;i<=M;i++)
{
scanf("%lf%lf",&p[i].x,&p[i].y);
}
if(N==0) //这个特判一定是不能少的
{
printf("0.000\n");
continue;
}
ans=INF;
for(i=1;i<M;i++) //枚举区间
{
ans=min(ans,cal(i));
}
printf("%.3lf\n",ans+eps);
continue;
}
return 0;
}