给一个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. Tomcat启动分析(Tomcat7.0)

    1)bin目录下的bootstrap.jar中的main方法启动Tomcat org.apache.catalina.startup.Bootstrap类下的main方法 可以看到Bootstrap类 ...

  2. Java实现Http服务器(四)

    (1)HTTPServer的监听启动 sun.net.httpserver.ServerImpl类中启动了Socket监听,ServerImpl的内部类Dispatch类启动了Http服务器的监听 / ...

  3. nodejs广播

    http://site.douban.com/185124/widget/notes/10805558/note/240909343/ http://t42dw.iteye.com/blog/1767 ...

  4. spring 动态数据源

    1.动态数据源:  在一个项目中,有时候需要用到多个数据库,比如读写分离,数据库的分布式存储等等,这时我们要在项目中配置多个数据库. 2.原理:   (1).spring 单数据源获取数据连接过程: ...

  5. android中保存一个ArrayList到SharedPreferences的方法

    保存: public static boolean saveArray() { SharedPrefernces sp=SharedPrefernces.getDefaultSharedPrefern ...

  6. Android MAVEN项目标准目录结构

    1.标准目录结构: src -main      –bin 脚本库      –java java源代码文件      –resources 资源库,会自动复制到classes目录里      –fi ...

  7. wcf托管在IIS上,提示未能加载

    “/”应用程序中的服务器错误. 未能加载文件或程序集“ZBMYunCoreLib.DLL”或它的某一个依赖项.找不到指定的模块. 说明: 执行当前 Web 请求期间,出现未经处理的异常.请检查堆栈跟踪 ...

  8. Google Map API 学习五

    今天其实收货很大的 1.InfoWindow google.maps.InfoWindow class An overlay that looks like a bubble and is often ...

  9. Linux cat命令详解

    本文主要内容源自网络,参考资料如下: 华夏名网,linux cat命令详解,http://www.sudu.cn/info/html/edu/20070101/290711.html 命令格式:cat ...

  10. oracle自动编号

    oracle自动编号 在access中有自动编号的数据类型,MSSQL和MYSQL也都有自动增长的数据类型,插入记录时不用操作此字段,会自动获得数据值,而oracle没有自动增长的数据类型,我们需要建 ...