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;
}