bzoj 2508: 简单题 — 数学
Contents
2508: 简单题
Time Limit: 10 Sec Memory Limit: 512 MB Sec Special Judge
Description
求一个点使得它到平面上所有直线距离平方和最小。
你需要实现以下3种操作:
1. 平面上加入一条直线;
2. 删除一条已加入的直线;
3. 求一个点到平面上所有直线距离平方和最小,你需要输出这个最小值。
Input
第1行包含一个整数N,表示了操作数目。接下来N行操作属于下列3种格式之一:
Output
输出行数等于查询操作的次数,每行输出每次查询操作所要求的最小值,保留两位小数。
Sample Input
10
0 0.0 0.0 1.0 0.0
2
0 0 1 1 1
2
0 0 2 1 2
2
1 2
2
1 3
2
0 0.0 0.0 1.0 0.0
2
0 0 1 1 1
2
0 0 2 1 2
2
1 2
2
1 3
2
Sample Output
0.00
0.50
2.00
2.00
0.00【数据规模与约定】
对于10%的数据,N ≤ 25;
对于50%的数据,N ≤ 1000;
对于50%的数据,查询操作不超过10次;
对于70%的数据,N ≤ 20000;
对于100%的数据,N ≤ 120000。
0.50
2.00
2.00
0.00【数据规模与约定】
对于10%的数据,N ≤ 25;
对于50%的数据,N ≤ 1000;
对于50%的数据,查询操作不超过10次;
对于70%的数据,N ≤ 20000;
对于100%的数据,N ≤ 120000。
HINT
一个点到直线Ax+By+C=0 的距离的平方公式是

所以我们就可以展开化简成![]()
那么,怎么求他的最值
对于一个正常函数,求最值可求导,导数为0 时就是最值
那么对于一个多变量的函数,我们可以分别对于每一个变量求 (偏)导,得到的解就是最值所在的位置
关于偏导具体可以看一下维基或者百度百科
然后就求一下偏导算一下就好了,剩下就是细节问题了
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define inf 1000000007
#define ll long long
#define N 120010
#define db double
struct qaz{db a,b,c;}a[N];
int n,tot,ji;
db x,y,xx,yy;
db A,B,C,D,E,F;
void ins()
{
int p=++tot;ji++;
a[p].a=y-yy;a[p].b=xx-x;a[p].c=y*(x-xx)-x*(y-yy);
db tp=(a[p].a*a[p].a+a[p].b*a[p].b);
A+=a[p].a*a[p].a/tp;B+=a[p].b*a[p].b/tp;
C+=2*a[p].a*a[p].b/tp;D+=2*a[p].a*a[p].c/tp;
E+=2*a[p].b*a[p].c/tp;F+=a[p].c*a[p].c/tp;
}
void del(int p)
{
ji--;db tp=(a[p].a*a[p].a+a[p].b*a[p].b);
A-=a[p].a*a[p].a/tp;B-=a[p].b*a[p].b/tp;
C-=2*a[p].a*a[p].b/tp;D-=2*a[p].a*a[p].c/tp;
E-=2*a[p].b*a[p].c/tp;F-=a[p].c*a[p].c/tp;
}
db ans,f[3][4];
#define eps 1e-5
void sol()
{
f[1][1]=2*A;f[1][2]=C;f[1][3]=-D;
f[2][1]=C;f[2][2]=2*B;f[2][3]=-E;
db tx,ty,tt;
if(abs(f[1][1])<eps)
{
if(abs(f[1][2])<eps) tx=0,ty=f[2][3]/f[2][2];
else ty=f[1][3]/f[1][2],tx=(f[2][3]-f[2][2]*ty)/f[2][1];
}
else if(abs(f[2][2])<eps)
{
if(abs(f[2][1])<eps) ty=0,tx=f[1][3]/f[1][1];
else tx=f[2][3]/f[2][1],ty=(f[1][3]-f[1][1]*tx)/f[1][2];
}
else
{
tt=f[2][1]/f[1][1];f[2][1]=0;
f[2][2]-=tt*f[1][2];f[2][3]-=tt*f[1][3];
ty=(abs(f[2][2])<eps)?0:f[2][3]/f[2][2];
tx=(abs(f[1][1])<eps)?0:(f[1][3]-f[1][2]*ty)/f[1][1];
}
ans=abs(A*tx*tx+B*ty*ty+C*tx*ty+D*tx+E*ty+F);
if(ans<eps) puts("0.00");
else printf("%.2lf\n",ans);
}
int main()
{
scanf("%d",&n);
int op,p;
while(n--)
{
scanf("%d",&op);
if(!op)
{
scanf("%lf%lf%lf%lf",&x,&y,&xx,&yy);
ins();
}
else if(op==1)
{
scanf("%d",&p);
del(p);
}
else
{
if(!ji){puts("0.00");continue;}
sol();
}
}
return 0;
}
发表评论