codeforces 394E Lightbulb for Minister

题目

E. Lightbulb for Minister
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

The Minister for education is coming! Naturally, nobody wants to perform poorly in front of such a honored guest. However, two hours before the arrival it turned out that one of the classes has a malfunctioning lightbulb — for some reason it doesn't get enough energy. The solution was found quickly: all we've got to do is to change the location of the lightbulb so that it got the maximum amount of energy.

Everybody knows that the power of the lightbulb equals , where C is some constant value and ri is the Euclidean distance from the bulb to the i-th generator. Consequently, our task is to minimize . Of course, we know the positions of all generators.

The bulb should be on the ceiling of the class. The ceiling of the class is in the form of a strictly convex m-gon (the class itself has the form of a right prism with a strictly convex m-gon at the bottom). Help to find the optimum location for the bulb. Assume that all generators are in the plane of the class ceiling. Consider that the plane of the class ceiling has some Cartesian coordinate system introduced.

Input

The first line contains integer n (2 ≤ n ≤ 105) — the number of generators. Each of the next n lines contains a pair of integers xiyi, representing the coordinates of the i-th generator in the plane of the class ceiling. It's guaranteed that no two generators have the same location.

The next line contains integer m (3 ≤ m ≤ 105) — the number of vertexes in the convex polygon that describes the ceiling of the class. Each of the following m lines contains a pair of integers pi, qi, representing the coordinates of the i-th point of the polygon in the clockwise order. It's guaranteed that the polygon is strictly convex.

The absolute value of all the coordinates don't exceed 106.

Output

Print a single real number — the minimum value of the sum of squares of distances from the generators to the point of the lightbulb's optimal position. The answer will be considered valid if its absolute or relative error doesn't exceed 10 - 4.

Sample test(s)
input
4
3 2
3 4
5 4
5 2
4
3 3
4 4
5 3
4 2
output
8.00000000
Note

We'll define a strictly convex polygon as a convex polygon with the following property: no three vertices of the polygon lie on the same line.




有n个点,然后有一个m边的凸边形,求在凸边形中的一个点,到n个点的距离平方和最小.
假设这个点是(x,y);  n个点的坐标(x[i],y[i])
求的是sigma((x-x[i])^2+(y-y[i])^2)=sigma(x^2-2x[i]*x+x[i]^2+y^2-2y[i]*x+y[i]^2)= n*x^2-2*sigma(x[i])*x+sigma(x[i]^2)+n*y^2-2*sigma(y[i])*y+sigma(y[i]^2)
分成x,y两部分,明显就是两个一元二次函数.当这两个一元二次函数取最小值(对称轴)时,可以得到一个点的坐标best(X,Y).
1. 如果best在凸m边形内部(把凸边形拆成n-2个三角形,看点和某个三角形的关系,这个点可以和三角形的顶点组成三个三角形,看三个三角形的面积和 和原三角形的面积是否相等)Ps:好像这种方法很SB..
如果是这种情况,答案很简单了
2.如果点不在多边形内,那我们最后取得点肯定在边上,因为一元二次函数在对称轴的两边是单调的.此时就,枚举多边形的边,把边上的点写成参数形式,代入最上面的式子,又是一个一元二次函数...


#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <math.h>
using namespace std;

struct Point{
    double x,y;
}con[100000+5],gen[100000+5];
int n,m;
double xsum2,xsum;
double ysum2,ysum;

inline double xmulti(Point p1, Point p2, Point p0)
{
    return (p1.x - p0.x) * (p2.y - p0.y) - (p1.y - p0.y) * (p2.x - p0.x);
}
inline bool in(Point best,Point a,Point b,Point c){
    double a1=fabs(xmulti(a,b,c))/2;
    double a2=fabs(xmulti(a,b,best))/2;
    double a3=fabs(xmulti(a,c,best))/2;
    double a4=fabs(xmulti(b,c,best))/2;
    double s=a2+a3+a4;
    if(fabs(s-a1)<=1e-3) return 1;//从1e-8改到1e-5再改到1e-3才过
    return 0;
}

int main(){
    while(~scanf("%d",&n)){
        xsum2=xsum=ysum2=ysum=0.0;
        for(int i=0;i<n;i++){
            scanf("%lf%lf",&gen[i].x,&gen[i].y);
            xsum2+=gen[i].x*gen[i].x,xsum+=gen[i].x*2;
            ysum2+=gen[i].y*gen[i].y,ysum+=gen[i].y*2;
        }
        scanf("%d",&m);
        for(int i=0;i<m;i++){
            scanf("%lf%lf",&con[i].x,&con[i].y);
        }
        /*   nX-xsum*X+xsum2
             n(X-(xsum/n)X+(xsum/2n)^2-(xsum/2n)^2)+xsum2
             n(X-xsum/2n)^2+xsum2-(xsum)^2/4n   */
        double X=xsum/(n*2.0);
        double Y=ysum/(n*2.0);
        bool ok=0;
        Point best;
        best.x=X,best.y=Y;
        for(int i=1;i+1<m;i++){
            if(in(best,con[0],con[i],con[i+1])){
                ok=1;break;
            }
        }
        if(ok){
            double ans=xsum2-(xsum*xsum)/(4.0*n)+ysum2-(ysum*ysum)/(4.0*n);
            printf("%.8lf\n",ans);
        }
        else{
            double ans=1000000000000000000.00;

            for(int i=0;i<m;i++){
                int s=i,t=(i+1)%m;
                double dx=con[t].x-con[s].x,dy=con[t].y-con[s].y;
                double a=con[s].x,b=con[s].y;
                double A=dx*dx+dy*dy,B=2*a*dx+2*b*dy-xsum/n*dx-ysum/n*dy;
                /*
                    X=a+dx*k,X=b+dy*k
                    (X-xsum/2n)^2+(Y-ysum/2n)^2
                    X^2 + xsum^2/(4*n^2) -xsum/n *X +
                    Y^2 + ysum^2/(4*n^2) -ysum/n *Y

                    (a+dx*k)^2+(b+dy*k)^2-xsum/n * (a+dx*k)-ysum/n *(b+dy*k)
                    dx^2*k^2+2*a*dx*k +dy^2*k^2+2*b*dy*k -xsum/n *dx*k - ysum/n*dy*k;
                    (dx^2+dy^2)*k^2 +(2*a*dx+2*b*dy-xsum/n*dx-ysum/n*dy)k;
                    Ak^2+Bk
                    k=-B/(2*A);
                */

                double k=(-B)/(2*A);
                if(k<0) k=0;
                else if(k>1) k=1;
                double x=a+dx*k,y=b+dy*k;
                // n(X-xsum/2n)^2+xsum2-(xsum)^2/4n
                double ss=n*(x-xsum/(2.0*n))*(x-xsum/(2.0*n))+xsum2-(xsum*xsum)/(4.0*n)+n*(y-ysum/(2.0*n))*(y-ysum/(2.0*n))+ysum2-(ysum*ysum)/(4.0*n);

                ans=min(ans,ss);
            }
            printf("%.8lf\n",ans);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值