题目链接:https://ac.nowcoder.com/acm/contest/3006/B
三分做法讲解:https://blog.csdn.net/huzujun/article/details/81187455
https://www.cnblogs.com/sugewud/p/9819304.html
本题可以这么理解,有唯一一个距离最小值(也就是我们要找的那个点),其左右都比它大,所以是一个凹陷下去的抛物线。
两种三分写法:
#include<iostream>
#include<cstdio>
#include<math.h>
using namespace std;
#define eps 1e-6
struct node
{
int x;
int y;
}a[110000];
int n;
double f(double x)
{
double maxdis=0;
for(int i=0;i<n;i++)
{
maxdis=max(maxdis,sqrt(1.0*(a[i].x-x)*(a[i].x-x)+1.0*a[i].y*a[i].y));
}
return maxdis;
}
double sanfen()
{
double l=-10000,r=10000,mid,rmid;
while(l+eps<r)
{
mid=(l+r)/2;
rmid=(r+mid)/2;
if(f(mid)<f(rmid))
r=rmid;
else
l=mid;
}
return f(l);
}
int main()
{
cin>>n;
for(int i=0;i<n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
double ans=sanfen();
cout<<ans<<endl;
return 0;
}
三分法例题:HDU4355
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4355
本题注意防止三分超时,取eps为1e-6,同时三分的范围取minpos,maxpos,而不是直接题目给的范围。
#include<iostream>
#include<cstdio>
#include<math.h>
using namespace std;
#define eps 1e-6
struct node
{
double pos;
double w;
}a[55000];
int n;
double min(double a,double b)
{
return a<b?a:b;
}
double max(double a,double b)
{
return a>b?a:b;
}
double f(double x)
{
double sum=0;
for(int i=0;i<n;i++)
{
sum+=pow(fabs(x-a[i].pos),3)*a[i].w;
}
return sum;
}
double sanfen(double ll ,double rr)
{
double l=ll,r=rr;
double mid,rmid;
while(l+eps<r)
{
mid=(l+r)/2;
rmid=(mid+r)/2;
if(f(mid)<f(rmid))
r=rmid;
else
l=mid;
}
return f(l);
}
int main()
{
int t;
cin>>t;
int tt=1;
while(t--)
{
scanf("%d",&n);
double minp=1000000,maxp=-1000000;
for(int i=0;i<n;i++)
{
scanf("%lf%lf",&a[i].pos,&a[i].w);
minp=min(a[i].pos,minp);
maxp=max(a[i].pos,maxp);
}
double ans=sanfen(minp,maxp);
printf("Case #%d: %d\n",tt++,(int)(floor(ans+0.5)));
}
return 0;
}