#1231 : Border Length

时间限制:1000ms
单点时限:1000ms
内存限制:256MB

描述

Garlic-Counting Chicken is a special species living around the Lake of Peking University.

A Garlic-Counting Chicken always flies out from home in the morning, goes to some fixed points looking for buuugs(a kind of worm), and comes back home in the afternoon.

Students from the School of Life Sciences find that, a Garlic-Counting Chicken always flies a straight line between two points, and its trace never goes across itself. The students want to find out the relationship between Garlic-Counting Chicken and the Lake. So they ask you to calculate the length of border of the common area between the Lake and one Garlic-Counting Chicken's daily trace.

输入

There are no more than 10 test cases.

For each test case, the first line contains n, the number of points on the trace in order. 1<=n<=1000.

Then n lines follow. Each line is a pair of integer x, y representing the n points' coordinates in order.

The last line contains three integers x,y and r  descripting the Lake, The Lake is a circle. Its center is at (x,y) and its radius is r.

The input ends if n = 0.

All |x|, |y|, |r| are smaller than 107.

输出

For each test case, output the length of the border of the common area. Please round the answer to the closest integer.

样例输入
4
-10 -10
-10 10
10 10
10 -10
-10 -10 20
4
-10 -10
-10 10
10 10
10 -10
-10 -10 4
4
-10 -10
-10 10
10 10
10 -10
0 0 10
4
-40 -40
-40 40
40 40
40 -40
0 0 50
0
样例输出
71
14
63
297
这样比较 好写,也好理解,但是还是写了挺长的代码

#include <iostream>
#include <algorithm>
#include <string.h>
#include <math.h>
#include <cstdio>
using namespace std;
const double eps=0.000000000001;
const double PI=acos(-1.0);
const int maxn=;
int dcmp(double a)
{
if(fabs(a)<eps)return ;
else return a>?:-;
}
struct Point
{
double x,y;
Point(double cx=,double cy=)
{
x=cx; y=cy;
}
double ang;
void Angle()
{
ang=atan2(y,x);
if(ang<){
ang+=*PI;
}
}
bool operator <(const Point &rhs)const
{
return ang<rhs.ang;
}
};
struct Circle
{
Point c;
double r;
Circle(Point cc=Point(,),double cr=)
{
c=cc; r=cr;
}
Point point(double a)
{
return Point(c.x+cos(a)*r, c.y+sin(a)*r);
}
};
Point operator -(Point A, Point B)
{
return Point(A.x-B.x,A.y-B.y);
}
Point operator +(Point A, Point B)
{
return Point(A.x+B.x,A.y+B.y);
}
bool operator ==(const Point &A, const Point &B)
{
return dcmp(A.x-B.x) == && dcmp(A.y-B.y)==;
}
double Dot(Point A,Point B)
{
return A.x*B.x+A.y*B.y;
}
double Length(Point A)
{
return sqrt(Dot(A,A));
}
double Cross(Point A, Point B)
{
return A.x*B.y - A.y*B.x;
}
Point TE[maxn];
Circle C;
struct Ins{
Point c;
int id;
}Poi[maxn];
struct Line
{
Point p;
Point v;
Line(Point cp=Point(,),Point cv=Point(,))
{
p=cp; v=cv;
}
Point point(double a)
{
Point te=Point(v.x*a,v.y*a);
return p+te;
}
};
int getLineCicleIntersection(Line L,Circle C, double &t1,double &t2,Point &A,Point &B)
{
double a=L.v.x,
b=L.p.x-C.c.x,
c=L.v.y,
d=L.p.y-C.c.y;
double e=a*a+c*c,
f=*(a*b+c*d),
g=b*b+d*d-C.r*C.r;
double delta=f*f-*e*g;
if(dcmp(delta)<)return ;
if(dcmp(delta)==)
{
t1=t2=-f/(*e);A=L.point(t1);
return ;
}
t1=(-f - sqrt(delta))/(*e);
A=L.point(t1);
t2=(-f + sqrt(delta))/(*e);
B=L.point(t2);
return ;
}
int judjiaodian(int n)
{
int nu=;
double t1,t2;
Point A,B;
for(int i=; i<n; i++)
{
int ge=getLineCicleIntersection(Line(TE[i],TE[i+]-TE[i]),C,t1,t2,A,B);//计算直线和圆交点 大白书模板
if(ge==)continue;
double s=Length(TE[i]-TE[i+]);
double d1=Length(TE[i]-A);
double d2=Length(TE[i+]-A);
if(ge==){
if(dcmp(s-d1)>=&&dcmp(s-d2)>=) //判断是否在这条边上
{
Poi[nu].c=A; Poi[nu].id=i; nu++;
}
continue;
}
double d3=Length(TE[i]-B);
double d4=Length(TE[i+]-B);
if(dcmp(s-d1)>=&&dcmp(s-d2)>=&&dcmp(s-d3)>=&&dcmp(s-d4)>=)//如果存在两个点
{
if(d1>d3){//应该把离起点进的点放在前面
swap(A,B);
}
Poi[nu].c=A; Poi[nu].id=i;nu++;
Poi[nu].c=B; Poi[nu].id=i;nu++;
}else if(dcmp(s-d1)>=&&dcmp(s-d2)>=)
{
Poi[nu].c=A; Poi[nu].id=i;nu++;
}else if(dcmp(s-d3)>=&&dcmp(s-d4)>=)
{
Poi[nu].c=B; Poi[nu].id=i;nu++;
}
}
int ge=;
for(int i=; i<nu; i++)
if( (Poi[i].c==Poi[ge-].c) == false )
Poi[ge++]=Poi[i];
nu=ge;
return nu;
}
int isPointInpolygon(Point p,int n)//判断点是否在多边形内
{
int wn=;
for(int i=; i<n; i++)
{
int k=dcmp(Cross(TE[i+]-TE[i],p-TE[i]));
int d1=dcmp(TE[i].y -p.y );
int d2=dcmp(TE[i+].y-p.y);
if( k > && d1 <= && d2 > )wn++;
if( k < && d2 <= && d1 > )wn--;
}
if(wn!=)return ;
return ;
}
void solve(int n)
{
int numOfInCir=;
double dist=;
for(int i=; i<n; i++)
{
if( dcmp( C.r-Length(TE[i]-C.c) )>= )numOfInCir++;
dist+=Length( TE[i+]-TE[i] );
}
if(isPointInpolygon(C.c,n))
{
if(numOfInCir==n){
printf("%.0lf\n",dist);
}else printf("%.0lf\n",PI**C.r);
return;
}
if(numOfInCir == n)
{
printf("%.0lf\n",dist);
}else printf("0\n");
}
Point Hu[maxn];
double judsolveCir(int nu,int n)
{
for(int i=; i<nu; i++)
{
Hu[i]=Poi[i].c-C.c;
Hu[i].Angle();
}
sort(Hu,Hu+nu);
Hu[nu]=Hu[];
Hu[nu].ang+=*PI;
double ans=;
for(int i=; i<nu; i++)
{
double ang=(Hu[i].ang+Hu[i+].ang)/;
if(ang>*PI)ang-=*PI;
Point t =C.point(ang);
if(isPointInpolygon(t,n))
{
ang=Hu[i+].ang-Hu[i].ang;
ans+=ang*C.r;
}
}
return ans;
}
Point TP[maxn];
double judsolvePoly(int nu, int n)
{
int loc=,num=;
for(int i=; i<n; i++)//融合那些点
{
TP[num++]=TE[i];
while(loc<nu&&Poi[loc].id<=i){
TP[num++]=Poi[loc].c; loc++;
}
}
loc=;
for(int i=; i<num; i++)
if((TP[i]==TP[loc-])==false )TP[loc++]=TP[i];
num=loc;
TP[num]=TP[];
double ans=;
for(int i=; i<num; i++)
{
Point tt=TP[i]+TP[i+];
tt.x*=0.5;
tt.y*=0.5;
double d1=Length(C.c-tt);
if(dcmp(C.r-d1)>=){
ans+=Length(TP[i+]-TP[i]);
}
}
return ans;
}
int main()
{
int n;
while(scanf("%d",&n)==&&n)
{
for(int i=; i<n; i++)
scanf("%lf%lf",&TE[i].x,&TE[i].y);
TE[n]=TE[];
scanf("%lf%lf%lf",&C.c.x,&C.c.y,&C.r);
int nu=judjiaodian(n);//计算交点
if(nu==||nu==){
solve(n);// 特判那几种情况
continue;
}
double ans=judsolveCir(nu,n);// 计算圆在多边形内的部分
ans+=judsolvePoly(nu,n);// 计算多边形在圆内的部分
printf("%.0lf\n",ans);
}
return ;
}
 

题意:

2015 北京网络赛 E Border Length hihoCoder 1231 树状数组 (2015-11-05 09:30)的更多相关文章

  1. 2015北京网络赛 D-The Celebration of Rabbits 动归+FWT

    2015北京网络赛 D-The Celebration of Rabbits 题意: 给定四个正整数n, m, L, R (1≤n,m,L,R≤1000). 设a为一个长度为2n+1的序列. 设f(x ...

  2. 2015北京网络赛 J Scores bitset+分块

    2015北京网络赛 J Scores 题意:50000组5维数据,50000个询问,问有多少组每一维都不大于询问的数据 思路:赛时没有思路,后来看解题报告也因为智商太低看了半天看不懂.bitset之前 ...

  3. 2015北京网络赛 Couple Trees 倍增算法

    2015北京网络赛 Couple Trees 题意:两棵树,求不同树上两个节点的最近公共祖先 思路:比赛时看过的队伍不是很多,没有仔细想.今天补题才发现有个 倍增算法,自己竟然不知道.  解法来自 q ...

  4. hihocoder 1391 树状数组

    #1391 : Countries 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 There are two antagonistic countries, countr ...

  5. 2015 北京网络赛 C Protecting Homeless Cats hihoCoder 1229 树状数组

    题意:求在平面上 任意两点连线,原点到这个点的距离小于d的点对有多少个,n=200000; 解: 以原点为圆心做一个半径为d的圆,我们知道圆内的点和园内以外的点的连线都是小于d的还有,圆内和园内的点联 ...

  6. hihocoder 1236(2015北京网络赛 J题) 分块bitset乱搞题

    题目大意: 每个人有五门课成绩,初始给定一部分学生的成绩,然后每次询问给出一个学生的成绩,希望知道在给定的一堆学生的成绩比这个学生每门都低或者相等的人数 因为强行要求在线查询,所以题目要求,每次当前给 ...

  7. 2015北京网络赛B题 Mission Impossible 6

    借用大牛的一张图片:模拟 #include<cstdio> #include<cmath> #include<cstring> #include<algori ...

  8. 2015北京网络赛 F Couple Trees 暴力倍增

    Couple Trees Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/problemset/problem/123 ...

  9. 2015北京网络赛 J Clarke and puzzle 求五维偏序 分块+bitset

    Clarke and puzzle Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://hihocoder.com/contest/acmicpc20 ...

随机推荐

  1. Vue+Vue-router微信分享功能

    在使用vue和vue-router路由框架已经开发过好几个项目了,其中也遇到不少坑,有些坑各种搜也没有找到非常理想的答案. vue学习相对来说还是比较简单,官方文档说明非常清楚(https://cn. ...

  2. Git:git diff 命令详解

    工作目录 vs 暂存区 $ git diff <filename> 意义:查看文件在工作目录与暂存区的差别.如果还没 add 进暂存区,则查看文件自身修改前后的差别.也可查看和另一分支的区 ...

  3. 蜕变成蝶~Linux设备驱动之CPU与内存和I/O

    那是世上最远的距离 思念让我无法去呼吸 你的一动和一举 占据我心里 陪我每个孤独无尽的夜里 用我心中盛放的画笔 描绘你微笑时的绚丽 爱让人痛彻心底 我却不怀疑 你的存在是我生命的奇迹 感受你的每一次的 ...

  4. Ubuntu16.04首次root登录设置

    一.首次登录root模式设置 当第一次安装并登录Ubuntu16.04系统时,系统默认只能使用guest模式登录.登录系统后,在图像界面的右上方的系统设置中可转换为普通用户模式. 在普通登录模式下,经 ...

  5. Java字符串连接的多种实现方法及效率对比

    JDK 1.8(Java 8)里新增String.join()方法用于字符串连接.本文基于<Java实现String.join()和效率比较>一文,分析和比较四种自定义实现与String. ...

  6. Visual Studio 2010 VS IDE 编辑界面出现绿色的点 去掉绿色的空格点

    Visual Studio  2010 VS IDE 编辑界面出现绿色的点 去掉绿色的空格点 Vs乱按一顿忽然出现一堆绿色的点,我去好难看,还不知道什么鬼,查了查其实就是个 每个点表示一个空格 让他显 ...

  7. thinkcmf 5关闭后台验证码

    控制器修改 D:\cmf\thinkcmf\app\admin\controller\PublicController.php 注释 /* $captcha = $this->request-& ...

  8. Linux下的搜索查找命令的详解(locate)

    3.locate locate 让使用者可以很快速的搜寻档案系统内是否有指定的档案.其方法是先建立一个包括系统内所有档案名称及路径的数据库,之后当寻找时就只需查询这个数据库,而不必实际深入档案系统之中 ...

  9. JavaSE 可变参数的方法重载

    /** * 可变参数的方法重载 */ class A { public void test(int a, int b) { System.out.println(a+", "+b) ...

  10. Java泛型 T.class的获取

    public interface BaseDao<T> { T get(String id); } import java.lang.reflect.ParameterizedType; ...