牛客网暑期ACM多校训练营(第三场)J 多边形与圆相交的面积
链接:https://www.nowcoder.com/acm/contest/141/J
题目描述
For example, if the coordinates of points of Tien-long country is (0,0), (2,0), (2, 2), (0, 2) in counter-clockwise order. And, one possible working place is at (1,1) and P=1, Q=2. Then, Eddy should choose a place to live which is closer to (1, 1) than half of the choices. The distance from the place Eddy will live to the working place will be about 0.7978845608.
输入描述:
The first line contains one positive integer N indicating the number of points of the polygon representing Tien-long country.
Each of following N lines contains two space-separated integer (xi,yi)
indicating the coordinate of i-th points. These points is given in clockwise or counter-clockwise order and form the polygon.
Following line contains one positive integer M indicating the number of possible working place Eddy can choose from.
Each of following M lines contains four space-separated integer xj,yj,P,Q, where (xj,yj) indicating the j-th working place is at (xj,yj) and
magic parameters is P and Q.
3<=N<=200
1<=M<=200
1<=P<Q<=200
|xi||yi||xj||yj|<=1000
It's guaranteed that the given points form a simple polygon.
输出描述:
Output M lines. For i-th line, output one number indicating the distance from the place Eddy will live to the i-th working place. Absolutely or relatively error within 10^-6 will be considered correct.
输入例子:
4
0 0
2 0
2 2
0 2
1
1 1 1 2
输出例子:
0.797884560809
-->
输入
4
0 0
2 0
2 2
0 2
1
1 1 1 2
输出
0.797884560809
输入
3
0 0
1 0
2 1
2
0 0 1 2
1 1 1 3
输出
1.040111537176
0.868735603376
题意 一个国家由n个点组成 m次询问 每次给出一个工作地点(xj,yj) 从国家里选取居住地点 要满足 选取的点比国家内Q/P的点离工作地点更近 问居住点到工作地点的距离
解析 我们可以二分答案mid 然后判断以(xj,yj)为圆心mid为半径的圆 与 国家相交的面积 与 国家面积的比值 二分下去。
AC代码 偷得模板 。。。。
#include <bits/stdc++.h>
#define LL long long
#define PI 3.1415926535897932384626
#define maxn 1000
#define EXIT exit(0);
#define DEBUG puts("Here is a BUG");
#define CLEAR(name, init) memset(name, init, sizeof(name))
const double eps = 1e-;
const int MAXN = (int)1e9 + ;
using namespace std;
#define Vector Point
int dcmp(double x) { return fabs(x) < eps ? : (x < ? - : ); }
struct Point {
double x, y; Point(const Point& rhs): x(rhs.x), y(rhs.y) { } //拷贝构造函数
Point(double x = 0.0, double y = 0.0): x(x), y(y) { } //构造函数 friend istream& operator >> (istream& in, Point& P) { return in >> P.x >> P.y; }
friend ostream& operator << (ostream& out, const Point& P) { return out << P.x << ' ' << P.y; } friend Vector operator + (const Vector& A, const Vector& B) { return Vector(A.x+B.x, A.y+B.y); }
friend Vector operator - (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y); }
friend Vector operator * (const Vector& A, const double& p) { return Vector(A.x*p, A.y*p); }
friend Vector operator / (const Vector& A, const double& p) { return Vector(A.x/p, A.y/p); }
friend bool operator == (const Point& A, const Point& B) { return dcmp(A.x-B.x) == && dcmp(A.y-B.y) == ; }
friend bool operator < (const Point& A, const Point& B) { return A.x < B.x || (A.x == B.x && A.y < B.y); } void in(void) { scanf("%lf%lf", &x, &y); }
void out(void) { printf("%lf %lf", x, y); }
}; template <class T> T sqr(T x) { return x * x;}
double Dot(const Vector& A, const Vector& B) { return A.x*B.x + A.y*B.y; } //点积
double Length(const Vector& A){ return sqrt(Dot(A, A)); }
double Angle(const Vector& A, const Vector& B) { return acos(Dot(A, B)/Length(A)/Length(B)); } //向量夹角
double Cross(const Vector& A, const Vector& B) { return A.x*B.y - A.y*B.x; } //叉积
double Area(const Point& A, const Point& B, const Point& C) { return fabs(Cross(B-A, C-A)); }
Vector normal(Vector x) { return Point(-x.y, x.x) / Length(x);}
double angle(Vector x) { return atan2(x.y, x.x);} Vector vecunit(Vector x){ return x / Length(x);} //单位向量
struct Circle {
Point c; //圆心
double r; //半径 Circle() { }
Circle(const Circle& rhs): c(rhs.c), r(rhs.r) { }
Circle(const Point& c, const double& r): c(c), r(r) { } Point point(double ang) const { return Point(c.x + cos(ang)*r, c.y + sin(ang)*r); } //圆心角所对应的点
double area(void) const { return PI * r * r; }
};
struct Line {
Point P; //直线上一点
Vector dir; //方向向量(半平面交中该向量左侧表示相应的半平面)
double ang; //极角,即从x正半轴旋转到向量dir所需要的角(弧度) Line() { } //构造函数
Line(const Line& L): P(L.P), dir(L.dir), ang(L.ang) { }
Line(const Point& P, const Vector& dir): P(P), dir(dir) { ang = atan2(dir.y, dir.x); } bool operator < (const Line& L) const { //极角排序
return ang < L.ang;
} Point point(double t) { return P + dir*t; }
}; bool InCircle(Point x, Circle c) { return dcmp(c.r*c.r - Length(c.c - x)*Length(c.c - x)) >= ;}
Point GetIntersection(Line a, Line b) //线段交点
{
Vector u = a.P-b.P;
double t = Cross(b.dir, u) / Cross(a.dir, b.dir);
return a.P + a.dir*t;
} bool OnSegment(Point p, Point a1, Point a2)
{
return dcmp(Cross(a1-p, a2-p)) == && dcmp(Dot(a1-p, a2-p)) < ;
}
int getSegCircleIntersection(Line L, Circle C, Point* sol)
{
Vector nor = normal(L.dir);
Line pl = Line(C.c, nor);
Point ip = GetIntersection(pl, L);
double dis = Length(ip - C.c);
if (dcmp(dis - C.r) > ) return ;
Point dxy = vecunit(L.dir) * sqrt(C.r*C.r - dis*dis);
int ret = ;
sol[ret] = ip + dxy;
if (OnSegment(sol[ret], L.P, L.point())) ret++;
sol[ret] = ip - dxy;
if (OnSegment(sol[ret], L.P, L.point())) ret++;
return ret;
} double SegCircleArea(Circle C, Point a, Point b) //线段切割圆
{
double a1 = angle(a - C.c);
double a2 = angle(b - C.c);
double da = fabs(a1 - a2);
if (da > PI) da = PI * 2.0 - da;
return dcmp(Cross(b - C.c, a - C.c)) * da * sqr(C.r) / 2.0;
} double PolyCiclrArea(Circle C, Point *p, int n)//多边形与圆相交面积
{
double ret = 0.0;
Point sol[];
p[n] = p[];
for(int i=;i<n;i++)
{
double t1, t2;
int cnt = getSegCircleIntersection(Line(p[i], p[i+]-p[i]), C, sol);
if (cnt == )
{
if (!InCircle(p[i], C) || !InCircle(p[i+], C)) ret += SegCircleArea(C, p[i], p[i+]);
else ret += Cross(p[i+] - C.c, p[i] - C.c) / 2.0;
}
if (cnt == )
{
if (InCircle(p[i], C) && !InCircle(p[i+], C)) ret += Cross(sol[] - C.c, p[i] - C.c) / 2.0, ret += SegCircleArea(C, sol[], p[i+]);
else ret += SegCircleArea(C, p[i], sol[]), ret += Cross(p[i+] - C.c, sol[] - C.c) / 2.0;
}
if (cnt == )
{
if ((p[i] < p[i + ]) ^ (sol[] < sol[])) swap(sol[], sol[]);
ret += SegCircleArea(C, p[i], sol[]);
ret += Cross(sol[] - C.c, sol[] - C.c) / 2.0;
ret += SegCircleArea(C, sol[], p[i+]);
}
}
return fabs(ret);
}
double PolygonArea(Point *po, int n) {
double area = 0.0;
for(int i = ; i < n-; i++) {
area += Cross(po[i]-po[], po[i+]-po[]);
}
return area * 0.5;
}
Point a[], b;
double p, q;
int main(){
int n, m;
scanf("%d", &n);
for(int i=;i<n;i++) a[i].in();
double ar = fabs(PolygonArea(a, n));
scanf("%d", &m);
for(int i=;i<m;i++){
b.in();
scanf("%lf%lf", &p, &q);
double l = , r = , num = , mid, aa = -p/q;
while(num--){
mid = (l+r)/;
Circle yuan(b, mid);
if(PolyCiclrArea(yuan, a, n)/ar < aa) l = mid;
else r = mid;
}
printf("%.10f\n", mid);
}
return ;
}
牛客网暑期ACM多校训练营(第三场)J 多边形与圆相交的面积的更多相关文章
- 牛客网暑期ACM多校训练营(第二场)J farm (二维树状数组)
题目链接: https://www.nowcoder.com/acm/contest/140/J 思路: 都写在代码注释里了,非常好懂.. for_each函数可以去看一下,遍历起vector数组比较 ...
- 牛客网 暑期ACM多校训练营(第二场)A.run-动态规划 or 递推?
牛客网暑期ACM多校训练营(第二场) 水博客. A.run 题意就是一个人一秒可以走1步或者跑K步,不能连续跑2秒,他从0开始移动,移动到[L,R]的某一点就可以结束.问一共有多少种移动的方式. 个人 ...
- 牛客网 暑期ACM多校训练营(第一场)A.Monotonic Matrix-矩阵转化为格子路径的非降路径计数,Lindström-Gessel-Viennot引理-组合数学
牛客网暑期ACM多校训练营(第一场) A.Monotonic Matrix 这个题就是给你一个n*m的矩阵,往里面填{0,1,2}这三种数,要求是Ai,j⩽Ai+1,j,Ai,j⩽Ai,j+1 ,问你 ...
- 2018牛客网暑期ACM多校训练营(第二场)I- car ( 思维)
2018牛客网暑期ACM多校训练营(第二场)I- car 链接:https://ac.nowcoder.com/acm/contest/140/I来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 ...
- 牛客网暑期ACM多校训练营(第一场) - J Different Integers(线段数组or莫队)
链接:https://www.nowcoder.com/acm/contest/139/J来源:牛客网 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 524288K,其他语言1048 ...
- 牛客网暑期ACM多校训练营(第九场) A题 FWT
链接:https://www.nowcoder.com/acm/contest/147/A来源:牛客网 Niuniu has recently learned how to use Gaussian ...
- 牛客网暑期ACM多校训练营(第九场)D
链接:https://www.nowcoder.com/acm/contest/147/D来源:牛客网 Niuniu likes traveling. Now he will travel on a ...
- 牛客网暑期ACM多校训练营(第二场)B discount
链接:https://www.nowcoder.com/acm/contest/140/B来源:牛客网 题目描述 White Rabbit wants to buy some drinks from ...
- 2018牛客网暑期ACM多校训练营(第一场)D图同构,J
链接:https://www.nowcoder.com/acm/contest/139/D来源:牛客网 同构图:假设G=(V,E)和G1=(V1,E1)是两个图,如果存在一个双射m:V→V1,使得对所 ...
- 牛客网暑期ACM多校训练营(第二场) I Car 思维
链接:https://www.nowcoder.com/acm/contest/140/I来源:牛客网 White Cloud has a square of n*n from (1,1) to (n ...
随机推荐
- 微信小程序组件解读和分析:一、view(视图容器 )
view组件说明: 视图容器 跟HTML代码中的DIV一样,可以包裹其他的组件,也可以被包裹在其他的组件内部.用起来比较自由随意,没有固定的结构. view组件的用法: 示例项目的wxml ...
- centos启用socks5服务
直接在终端用 root 安装 *** 官方客户端 apt-get install python-pip -ypip install shadowsocks 然后编辑 /etc/shadowsocks. ...
- Struts2 前端与后台之间传值问题
老是被前端与后台之间的传值给弄糊涂了,特此写一篇blog进行总结. 一. 前端向后台传值 (1)属性驱动 属性驱动是指在Action类里,包含表单里对应的字段(字段名称一样),同时设置对应的gette ...
- Photoshop 注册破解
本机测试环境为Photoshop cs4 破解方式一: 打开C:\windows\system32\drivers\etc\"找到 hosts 文件, 右键点击--打开方式---记事本,然后 ...
- HYSBZ 1086 王室联邦 (树的分块)
题意:国王想把他的国家划分成若干个省.他的国家有n个城市,是一棵树,即n-1条边,编号为1..n.为了防止管理太过分散,每个省至少要有B个城市,为了能有效的管理,每个省最多只有3B个城市.每个省必须有 ...
- COGS 942. [東方S3] 比那名居天子
Problem 1 比那名居天子(tenshi.cpp/c/pas) 题目描述 在幻想乡,比那名居天子是管理着『要石』的天人.『要石』是能够引发和镇压地震的存在,当然也可以用来改变地形.因为在幻想乡引 ...
- Jenkins执行sudo权限的设置
Jenkins系统中添加执行脚本的时候,有一些命令是需要sudo权限和来执行的,可以在root权限下添加一下Jenkins账号的权限 1.添加不需要密码可sudo执行指定命令的权限 cd /etc c ...
- c语言 错误记录
1.预处理错误 #include <> //系统内部的 #include "" // 自定义的 遇到 not find------解决方案:gcc -I 跟查找 ...
- 【整理】treeGrid 树形表格
treeGrid 树形表格 https://fly.layui.com/extend/treeGrid/
- qobject_cast
void QLadderDiagramItem::GetMainForm(DoType sourceType){ for each (QWidget *w in qApp->topLevelWi ...