给一个1000个点的多边形(从某个点依次按照外形给出每个节点),这个多边形不一定是凸多边形

再给一个圆,问这个多边形与圆相交区域的周长

我们将这个问题分成两个部分,第一部分是求线段在圆内的长度,第二部分是求圆弧的长度。

对于第一个部分,求线段在圆内的长度,

注意线段两端都在圆外边但是线段与圆有交点的情况。相切的情况可以不去考虑

第二个部分,我们在求第一部分时顺带求出所有线段与圆的交点,依次枚举每段圆弧,我们需要判断这段圆弧是否在多边形内

其实我们只需求出圆弧的中点,对于中点,判断是否在多边形内,射线法或者转角法均可,如果在多边形内就把其长度累加到答案中。

另外特殊判断一下整个圆都在多边形内部的情况

程序是赛后写出来的,还没有提交过_(:зゝ∠)_

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<queue>
#include<string>
#include<sstream>
#define eps 1e-9
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define rep(i,j,k) for(int i=j;i<=k;i++)
#define MAXN 1005
#define MAXM 40005
#define INF 0x3fffffff
#define PB push_back
#define MP make_pair
#define X first
#define Y second
#define clr(x,y) memset(x,y,sizeof(x));
using namespace std;
typedef long long LL;
int i,j,k,n,m,x,y,T,big,cas,num,len;
bool flag; const double pi=acos(-1.0);
int dcmp(double x) {
if(fabs(x) < eps) return ;
else
return x < ? - : ;
}
struct Vector
{
double x, y;
Vector (double x=, double y=) :x(x),y(y) {}
Vector operator + (const Vector &B) const { return Vector (x+B.x,y+B.y); }
Vector operator - (const Vector &B) const { return Vector(x - B.x, y - B.y); }
Vector operator * (const double &p) const { return Vector(x*p, y*p); }
Vector operator / (const double &p) const { return Vector(x/p, y/p); }
double operator * (const Vector &B) const { return x*B.x + y*B.y;}//点积
double operator ^ (const Vector &B) const { return x*B.y - y*B.x;}//叉积
bool operator < (const Vector &b) const { return x < b.x || (x == b.x && y < b.y); }
bool operator ==(const Vector &b) const { return dcmp(x-b.x) == && dcmp(y-b.y) == ; }
};
typedef Vector Point;
Point Read(){double x, y;scanf("%lf%lf", &x, &y);return Point(x, y);}
double Length(Vector A){ return sqrt(A*A); }//向量的模
double Angle(Vector A, Vector B){return acos(A*B / Length(A) / Length(B)); }//向量的夹角,返回值为弧度
double Area2(Point A, Point B, Point C){ return (B-A)^(C-A); }//向量AB叉乘AC的有向面积
Vector VRotate(Vector A, double rad){return Vector(A.x*cos(rad) - A.y*sin(rad), A.x*sin(rad) + A.y*cos(rad));}//向量A旋转rad弧度
Point PRotate(Point A, Point B, double rad){return A + VRotate(B-A, rad);}//将B点绕A点旋转rad弧度
Vector Normal(Vector A){double l = Length(A);return Vector(-A.y/l, A.x/l);}//求向量A向左旋转90°的单位法向量,调用前确保A不是零向量 Point GetLineIntersection/*求直线交点,调用前要确保两条直线有唯一交点*/(Point P, Vector v, Point Q, Vector w){double t = (w^(P - Q)) / (v^w);return P + v*t;}//在精度要求极高的情况下,可以自定义分数类
double DistanceToLine/*P点到直线AB的距离*/(Point P, Point A, Point B){Vector v1 = B - A, v2 = P - A;return fabs(v1^v2) / Length(v1);}//不加绝对值是有向距离
double DistanceToSegment/*点到线段的距离*/(Point P, Point A, Point B)
{
if (A==B) return Length(P-A);
Vector v1=B-A,v2=P-A,v3=P-B;
if (dcmp(v1*v2)<) return Length(v2);else
if (dcmp(v1*v3)>) return Length(v3);else
return fabs(v1^v2)/Length(v1);
} Point GetLineProjection/*点在直线上的射影*/(Point P, Point A, Point B)
{
Vector v=B-A;
return A+v*((v*(P-A))/(v*v));
} bool OnSegment/*判断点是否在线段上(含端点)*/(Point P,Point a1,Point a2)
{
Vector v1=a1-P,v2=a2-P;
if (dcmp(v1^v2)== && min(a1.x,a2.x)<=P.x && P.x<=max(a1.x,a2.x) && min(a1.y,a2.y)<=P.y && P.y<=max(a1.y,a2.y)) return true;
return false;
} bool SegmentInter/*线段相交判定*/(Point a1, Point a2, Point b1, Point b2)
{
//if (OnSegment(a1,b1,b2) || OnSegment(a2,b1,b2) || OnSegment(b1,a1,a2) || OnSegment(b2,a1,a2)) return 1;
//如果只判断线段规范相交(不算交点),上面那句可以删掉
double c1=(a2-a1)^(b1-a1),c2=(a2-a1)^(b2-a1);
double c3=(b2-b1)^(a1-b1),c4=(b2-b1)^(a2-b1);
return dcmp(c1)*dcmp(c2)< && dcmp(c3)*dcmp(c4)<;
} bool InTri/*判断点是否在三角形内*/(Point P, Point a,Point b,Point c)
{
if (dcmp(fabs((c-a)^(c-b))-fabs((P-a)^(P-b))-fabs((P-b)^(P-c))-fabs((P-a)^(P-c)))==) return true;
return false;
} double PolygonArea/*求多边形面积,注意凸包P序号从0开始*/(Point *P ,int n)
{
double ans = 0.0;
for(int i=;i<n-;i++)
ans+=(P[i]-P[])^(P[i+]-P[]);
return ans/;
}
bool CrossOfSegAndLine/*判断线段是否与直线相交*/(Point a1,Point a2,Point b1,Vector b2)
{
if (OnSegment(b1,a1,a2) || OnSegment(b1+b2,a1,a2)) return true;
return dcmp(b2^(a1-b1))*dcmp(b2^(a2-b1))<;
} Point stand(Point u)
{
double len=Length(u);
return u/len;
} int intersCL(Point cen,double R,Point A,Point B,Point &I1,Point &I2)//直线与圆的交点
{
double dis=DistanceToLine(cen,A,B);
int tt=dcmp(dis-R);
if (dcmp(dis-R)>) return ;
if (dcmp(dis-R)==)
{
I1=GetLineProjection(cen,A,B);
return ;
} double x=sqrt(R*R-dis*dis);
Point p=GetLineProjection(cen,A,B);
Vector v=stand(A-B)*x;
I1=p+v;
I2=p-v;
return ;
} Point p[],c;
double R,ans; bool cmp(Point a,Point b)
{
return atan2(a.y,a.x)<atan2(b.y,b.x);
} //转角发判定点P是否在多边形内部
int isPointInPolygon(Point P, Point* Poly, int n)
{
int wn=;
for(int i = ; i < n; ++i)
{
if(OnSegment(P, Poly[i], Poly[(i+)%n])) return -; //在边界上
int k = dcmp((Poly[(i+)%n] - Poly[i])^( P - Poly[i]));
int d1 = dcmp(Poly[i].y - P.y);
int d2 = dcmp(Poly[(i+)%n].y - P.y);
if(k > && d1 <= && d2 > ) wn++;
if(k < && d2 <= && d1 > ) wn--;
}
if(wn != ) return ; //内部
return ; //外部
} Point middle (Point A,Point B)
{
return Point((A.x+B.x)/,(A.y+B.y)/);
}
vector <Point> pt; Point print(Point A)
{
printf("%lf %lf\n",A.x,A.y);
} int main()
{
while (scanf("%d",&n),n)
{
for (i=;i<n;i++) p[i]=Read();
c=Read();scanf("%lf",&R);
int tot=;
for (i=;i<n;i++)
{
Vector v1=p[i]-p[(i-+n)%n];
Vector v2=p[(i+)%n]-p[i];
tot+=dcmp(v1^v2);
}
if (tot<)
{
for (i=;i<n/;i++)
{
swap(p[i],p[n-i-]);
}
}
ans=;
pt.clear();
for (i=;i<n;i++)
{
Point A=p[i],B=p[(i+)%n];
Point I1,I2;
int num=intersCL(c,R,A,B,I1,I2);
if (num<=) continue; bool T1=OnSegment(I1,A,B);
bool T2=OnSegment(I2,A,B);
bool T3=OnSegment(A,I1,I2);
bool T4=OnSegment(B,I1,I2); if (A==I1) pt.PB(A-c);
if (A==I2) pt.PB(A-c);
if (B==I1) pt.PB(B-c);
if (B==I2) pt.PB(B-c); if (T1 && T2)
{
ans+=Length(I2-I1);
pt.PB(I1-c);pt.PB(I2-c);
}else
if (T3 && T4)
{
ans+=Length(A-B);
}else
if (!T1 && !T2)
{
continue;
}else
if (T1)
{
if (T4) ans+=Length(I1-B);
else ans+=Length(I1-A); pt.PB(I1-c);
}else
{
if (T4) ans+=Length(I2-B);
else ans+=Length(I2-A); pt.PB(I2-c);
} }
sort(pt.begin(),pt.end(),cmp);
unique(pt.begin(),pt.end(),cmp); int sz=pt.size(); if (sz== && ans==)
{
printf("%d\n",(int)round(pi**R));
continue;
} for (i=;i<sz;i++)
{
Point p1=pt[i];
Point p2;
if (i==sz-)
{
p2=pt[];
}else
p2=pt[i+];
double a1=atan2(p1.y,p1.x);
double a2=atan2(p2.y,p2.x);
if (i==sz-) a2+=*pi; double a3=(a1+a2)/; Point pm=VRotate(Point(R,0.0),a3); pm=stand(pm)*R+c; if (isPointInPolygon(pm,p,n)>)
{
ans+=(a2-a1)*R;
}
}
printf("%d\n",(int)round(ans));
}
return ;
}

hihocoder 北大网络赛 E.的更多相关文章

  1. ACM总结——2017区域赛网络赛总结

    从省赛回来至今4周,每周周末都在打网络赛,每次都是划水,总结下自己弱弱的ACM吧!划水水~~ 首先是新疆赛区,基本上都是图论相关的东西,全靠队友,自己翻水水,实力躺了5道. 然后是沈阳赛区,终于有点贡 ...

  2. HDU 5875 Function -2016 ICPC 大连赛区网络赛

    题目链接 网络赛的水实在太深,这场居然没出线zzz,差了一点点,看到这道题的的时候就剩半个小时了.上面是官方的题意题解,打完了才知道暴力就可以过,暴力我们当时是想出来了的,如果稍稍再优化一下估计就过了 ...

  3. 大连网络赛 1006 Football Games

    //大连网络赛 1006 // 吐槽:数据比较水.下面代码可以AC // 但是正解好像是:排序后,前i项的和大于等于i*(i-1) #include <bits/stdc++.h> usi ...

  4. 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree

    // 树形DP CCPC网络赛 HDU5834 Magic boy Bi Luo with his excited tree // 题意:n个点的树,每个节点有权值为正,只能用一次,每条边有负权,可以 ...

  5. (四面体)CCPC网络赛 HDU5839 Special Tetrahedron

    CCPC网络赛 HDU5839 Special Tetrahedron 题意:n个点,选四个出来组成四面体,要符合四面体至少四条边相等,若四条边相等则剩下两条边不相邻,求个数 思路:枚举四面体上一条线 ...

  6. HDU-4041-Eliminate Witches! (11年北京网络赛!!)

    Eliminate Witches! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  7. hihocoder1236(北京网络赛J):scores 分块+bitset

    北京网络赛的题- -.当时没思路,听大神们说是分块+bitset,想了一下发现确实可做,就试了一下,T了好多次终于过了 题意: 初始有n个人,每个人有五种能力值,现在有q个查询,每次查询给五个数代表查 ...

  8. 36th成都区域赛网络赛 hdoj4039 The Social Network(建图+字符串处理)

    这题是某年成都区域赛网络赛的一题. 这题思路非常easy,可是从时间上考虑,不妨不要用矩阵存储,我用的链式前向星. 採用线上查询.利用map对字符串编号,由于非常方便.要推荐的朋友,事实上就是朋友的朋 ...

  9. hdu5017:补题系列之西安网络赛1011

    补题系列之西安网络赛1011 题目大意:给定一个椭球: 求它到原点的最短距离. 思路: 对于一个椭球的标准方程 x^2/a^2 + y^2/b^2 +z^2/c^2=1 来说,它到原点的最短距离即为m ...

随机推荐

  1. StartSSL免费SSL证书成功申请-HTTPS让访问网站更安全

    StartSSL免费SSL证书成功申请-HTTPS让访问网站更安全 一.StartSSL个人证书登录申请 1.StartSSL官网: 1.官方首页:http://www.startssl.com/ 2 ...

  2. A Diagram Designer

    源码:http://files.cnblogs.com/jumahe/DiagramDesigner.rar 环境:VS2010

  3. [BZOJ 1025] [SCOI2009] 游戏 【DP】

    题目链接:BZOJ - 1025 题目分析 显然的是,题目所要求的是所有置换的每个循环节长度最小公倍数的可能的种类数. 一个置换,可以看成是一个有向图,每个点的出度和入度都是1,这样整个图就是由若干个 ...

  4. DJANGO不同应用之间的用户迁移

    因为重新规划新的项目,数据库表结构和以前不一定了,但是想保存以前的很多用户认证方面的东东. 于是看了一下DJANGO的导入导出功能. ~~~~~~~~~~~~~~~~~~~ 数据导入: python ...

  5. xmlns:android作用以及自定义布局属性

    要定制Android layout 中的 attributes关键是要明白android中命名空间定义如: xmlns:android="http://schemas.android.com ...

  6. gcc c语言中scanf输入格式不正确,清空缓冲区问题

    我的博客:www.while0.com 折磨了一下午,只因为fflush(stdin)再gcc里和vc里表现不一致.gcc里不能够清空缓冲区.直接上例子: #include <stdio.h&g ...

  7. C# 哈希表的实现

    8.4.2 Hashtable的代码实现   哈希表的实现较为复杂,为了简化代码,本例忽略了部分出错判断,在测试时请不要设key值为空.   1 using System; 2 public clas ...

  8. Node.js权威指南 (4) - 模块与npm包管理工具

    4.1 核心模块与文件模块 / 574.2 从模块外部访问模块内的成员 / 58 4.2.1 使用exports对象 / 58 4.2.2 将模块定义为类 / 58 4.2.3 为模块类定义类变量或类 ...

  9. haproxy实现mysql slave负载均衡

    简单画一个图: 一.服务器规划 192.168.116.132 (master)  -->写操作 192.168.116.129 (slave1)  -->读操作 192.168.116. ...

  10. Light OJ 1051 - Good or Bad

    题目大意: 给你一个字符串,字符串由大写字母和‘?’组成,大写字母可以变成任意一个字母.现在我们定义字符串, 如果有超过三个连续的元音字母或者连续五个辅音字母,那么我们称这个字符串是“BAD”,否则称 ...