Error Curves
题意
给你n个两次函数 y = ax^2 + bx + c,其中0 ≤ a ≤ 100 ,|b| ≤ 5000), c (|c| ≤ 5000),0≤x≤1000。 定义F(x)为x在[0,1000]这个范围内的所有函数的最大值,求F(x)的最小值。最大指的是对于某一个x最大的那个y,最小指的是全体的x范围中最大的那个最小。
思路
因为a>=0 所以都是开口向上的,如果F(n) 的 x/y( x<= 0 && x <= 1000),图像肯定是单调或者凸性的,所以直接三分就行了。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std ;
const double eps=1e-9 ;
const int maxn=1e5 +5 ;
double a[maxn],b[maxn],c[maxn];
int n;
double cal(double x)
{
double ans=a[1 ]*x*x+b[1 ]*x+c[1 ];
for (int i=2 ;i<=n;i++)
ans=max(ans,a[i]*x*x+b[i]*x+c[i]);
return ans;
}
double solve(double l,double r)
{
double mid,mid2;
while (r-l>eps){
mid=(l+r)/2 ;
mid2=(mid+r)/2 ;
if (cal(mid)>=cal(mid2)){
l=mid;
}else r=mid2;
}
return cal(l);
}
int main()
{
int T;
scanf ("%d" ,&T);
for (int cas=1 ;cas<=T;cas++){
scanf ("%d" ,&n);
for (int i=1 ;i<=n;i++){
scanf ("%lf%lf%lf" ,&a[i],&b[i],&c[i]);
}
printf ("%.4f\n" ,solve(0 ,1000 ));
}
return 0 ;
}
The Moving Points
题意
给定n个点的坐标和它x和y方向的分速度,要求在任意时刻两两点之间距离最大值中的最小值。 根据距离公式可以推断出对于某两个点在t逐渐增大的过程中距离服从二次函数。
思路
易知是凸函数,对于时间t三分求最大距离。枚举范围0~1e10。
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std ;
const double eps=1e-9 ;
const int maxn=305 ;
double x[maxn],y[maxn],vx[maxn],vy[maxn];
int n;
double cal(double t)
{
double ans=0 ;
for (int i=1 ;i<=n;i++){
for (int j=i+1 ;j<=n;j++){
double x1=x[i]+vx[i]*t;
double y1=y[i]+vy[i]*t;
double x2=x[j]+vx[j]*t;
double y2=y[j]+vy[j]*t;
ans=max(ans,sqrt ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)));
}
}
return ans;
}
double solve(double l,double r)
{
double mid,mid2;
while (r-l>eps){
mid=(l+r)/2 ;
mid2=(mid+r)/2 ;
if (cal(mid)>=cal(mid2)){
l=mid;
}else r=mid2;
}
return l;
}
int main()
{
int T;
scanf ("%d" ,&T);
for (int cas=1 ;cas<=T;cas++){
scanf ("%d" ,&n);
for (int i=1 ;i<=n;i++){
scanf ("%lf%lf%lf%lf" ,&x[i],&y[i],&vx[i],&vy[i]);
}
double t=solve(0 ,1e10 );
printf ("Case #%d: %.2lf %.2lf\n" ,cas,t,cal(t));
}
return 0 ;
}