codeforces 394E Lightbulb for Minister 简单几何

题目链接:点我点我

题意:给定n个点。下面n行给出这n个点坐标。

给定m个点,下面m行给出这m个点坐标。 这m个点是一个凸包,顺时针给出的。

问:在凸包上任意找一个点(x, y) 使得这个点距离n个点的距离平方和最小。

问这个最小的距离平方和是多少。

思路:

首先化简一下公式,把变量(x,y)提出来会发现是一个简单的函数,且开口向上,所以有唯一解,解出这个(x,y) 记为 (good_x, good_y)

但这个点可能不是坐落在凸包内,若坐落在凸包外,则最优解一定是在凸包的边上,所以枚举每条边求个解就好了。

判断点在凸多边形内部用三角形面积相等即可。

#include <iostream>
#include <fstream>
#include <string>
#include <time.h>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#include <vector>
using namespace std;
template <class T>
inline bool rd(T &ret) {
    char c; int sgn;
    if (c = getchar(), c == EOF) return 0;
    while (c != ‘-‘ && (c<‘0‘ || c>‘9‘)) c = getchar();
    sgn = (c == ‘-‘) ? -1 : 1;
    ret = (c == ‘-‘) ? 0 : (c - ‘0‘);
    while (c = getchar(), c >= ‘0‘&&c <= ‘9‘) ret = ret * 10 + (c - ‘0‘);
    ret *= sgn;
    return 1;
}
template <class T>
inline void pt(T x) {
    if (x <0) {
        putchar(‘-‘);
        x = -x;
    }
    if (x>9) pt(x / 10);
    putchar(x % 10 + ‘0‘);
}
typedef long long ll;
typedef pair<int, int> pii;
const int N = 1e5+10;
const int inf = 1e9;
const double eps = 1e-4;
struct Point{
    double x, y;
    Point(double a = 0, double b = 0) :x(a), y(b){}
}a[N], b[N];
int n, m;
double cx, cy, C;
double good_x, good_y;
double cal(double x, double y){
    double ans = 0;
    for (int i = 0; i < n; i++)
        ans += (a[i].x - x)*(a[i].x - x) + (a[i].y - y)*(a[i].y - y);
    return ans;
}
double area(Point x, Point y, Point z){
    return abs(x.x*y.y  + y.x*z.y + z.x*x.y - x.x*z.y - y.x*x.y - z.x*y.y) / 2.0;
}
double work(Point x){
    double ans = 0;
    for (int i = 0; i < m; i++)
        ans += area(x, b[i], b[(i + 1) % m]);
    return ans;
}
double papa(Point x){
    return n*x.x*x.x + n*x.y*x.y - 2 * x.x*cx - 2 * x.y*cy;
}
Point cut(Point x, Point y, double k){
    return Point(x.x + k*(y.x - x.x), x.y + k*(y.y - x.y));
}
double hehe(Point x, Point y){
    double ans = min(papa(x), papa(y));
    if (y.x != x.x){
        double k = (y.y - x.y) / (y.x - x.x), b = x.y - k*x.x;
        double _x = (k*cy + cx - n*k*b) / n / (1 + k*k);
        if (_x < min(x.x, y.x) || _x > max(x.x, y.x))return ans;
        double _y = k*_x + b;
        ans = min(ans, papa(Point(_x, _y)));
    }
    else {
        if (min(x.y, y.y) <= good_y && good_y <= max(x.y, y.y))
            ans = min(ans, papa(Point(x.x, good_y)));
    }
    return ans;
}
int main(){
    rd(n);
    cx = cy = C = 0;
    for (int i = 0; i < n; i++){
        rd(a[i].x), rd(a[i].y);
        cx += a[i].x;
        cy += a[i].y;
        C += a[i].x*a[i].x + a[i].y*a[i].y;
    }
    rd(m);
    for (int i = 0; i < m; i++)rd(b[i].x), rd(b[i].y);
    good_x = (double)cx / n;
    good_y = (double)cy / n;
    if (abs(work(b[0]) - work(Point(good_x, good_y))) < eps)
        printf("%.10f\n", cal(good_x, good_y));
    else {
        double ans = 1e19;
        for (int i = 0; i < m; i++)
            ans = min(ans, hehe(b[i], b[(1 + i) % m]));
        printf("%.10f\n", ans + C);
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-06 19:48:14

codeforces 394E Lightbulb for Minister 简单几何的相关文章

CodeForces 703C Chris and Road (简单几何)

题意:有一个n边形的汽车向以速度v向x轴负方向移动,给出零时时其n个点的坐标.并且有一个人在(0,0)点,可以以最大速度u通过w宽的马路,到达(0,w)点.现在要求人不能碰到汽车,人可以自己调节速度.问人到达马路对面的最小时间是多少? 析:这个题是一个简单的分类讨论,很明显只有两种情况,第一种,直接到达w,不会被车撞到,答案就是w/u, 第二种是切着车过去,或者是等车过去再过去,只要枚举车的每个顶点,找到最后通过y轴的点就好,或者根本不会与车相切. 代码如下: #pragma comment(l

Python下opencv使用笔记(二)(简单几何图像绘制)

简单几何图像一般包括点.直线.矩阵.圆.椭圆.多边形等等.首先认识一下opencv对像素点的定义.图像的一个像素点有1或者3个值,对灰度图像有一个灰度值,对彩色图像有3个值组成一个像素值,他们表现出不同的颜色. 那么有了点才能组成各种多边形. (一)首先绘制直线 函数为:cv2.line(img,Point pt1,Point pt2,color,thickness=1,line_type=8 shift=0) 有值的代表有默认值,不用给也行.可以看到这个函数主要接受参数为两个点的坐标,线的颜色

Codeforces 828B Black Square(简单题)

Codeforces 828B Black Square(简单题) Description Polycarp has a checkered sheet of paper of size n?×?m. Polycarp painted some of cells with black, the others remained white. Inspired by Malevich's "Black Square", Polycarp wants to paint minimum pos

POJ 1473 There&#39;s Treasure Everywhere!(简单几何)

There's Treasure Everywhere! 博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/40865611 题目大意: 给你一个字符串,里面有许多的操作,前面的数字是移动的距离,后面的英文表示移动的方向,问最后从远点出发的一个点回落在什么地方以及距离出发点的距离是多少. 解题思路: 题目本身并不是很难,也没有什么坑点,没什么好说的,字符串处理的时候细心一点就行. PS:每组后面需要加一个回车,因为这个PE了一次

简单几何 UVA 11178 Morley&#39;s Theorem

题目传送门 题意:莫雷定理,求三个点的坐标 分析:训练指南P259,用到了求角度,向量旋转,求射线交点 /************************************************ * Author :Running_Time * Created Time :2015/10/21 星期三 15:56:27 * File Name :UVA_11178.cpp ************************************************/ #include

HDU 4793 Collision + HDU 4798 Skycity 简单几何

HDU 4793 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4793 题意:给一个以(0,0)为圆心半径为R的圆形区域,中间放着一个(0,0)为圆心半径为Rm的圆盘,在坐标(x,y)处(严格在圆形区域外)放着一枚半径为r的硬币,运动方向和速度为(vx,vy),在运动中碰到圆盘时,会按碰撞问题反弹(圆盘是固定不动的),问硬币会在圆形区域里呆多长时间(硬币只要有一点点在圆形区域里就记为硬币在圆形区域内). 思路:首先先计算出硬币在移动过程中如果不与圆盘

Codeforces 413B Spyke Chatting(数论简单)

题目链接:Codeforces 413B Spyke Chatting 题目大意:n个人,m种聊天器,k次发送消息,然后给出n*m的矩阵,如果g[i][j]为1,则表示i号人会使用j号聊天器,接着给出k次消息发送者和聊天器,如果i在j种聊天器上发送了一条消息,那么所有使用j种聊天器的人都会接受到消息.现在要求每个人会接受到几条消息,自己发送的不算. 解题思路:分别记录每个聊天器上有多少个消息,以及每个人发送了多少条消息,然后计算每个人接受到多少条消息的时候只要将这个人所使用的各个聊天器消息数取和

hdu5365 简单几何问题

http://acm.hdu.edu.cn/showproblem.php?pid=5365 Problem Description AFA is a girl who like runing.Today,he download an app about runing .The app can record the trace of her runing.AFA will start runing in the park.There are many chairs in the park,and

Codeforces Round #231 (Div. 2) E.Lightbulb for Minister

题意:有n个点,问在一个m边形内哪个点与这n个点的距离平方和最小 题解:(ai-a0)^2=ai*ai+a0*a0-a*ai*a0 合起来就是a1*a1+...+an*an+n*a0*a0-2*a0*(a1+...+an) 取导数就是2*n*a0-2*a0*(a1+...+an) 可以知道在x y轴上各取n个点的平均值就是最小值 至于在不在m边形里,判断一下吧 不在里面就在线上,m条边求下导就出来了