以下摘自SPOJ泛做表格:

题意:给定一个星形多边形,而且给出了一个可以看到形内所有点的位置(我们称这个点为观察点),让你判断有多少个点位于多边形内。

时间复杂度:O(mlogn)

将多边形上的点按极角排序,观察点与多边形上任意相邻两点形成若干个三角形,再按照极角查找给定点可能位于哪个三角形,最后用叉积判断它是否真的在那个三角形内。

注意细节,给几组数据:

input


-
-
- - -
- - -
-
-
-
-
-
- -
- -
- -
- -
- -
-
-
-
-
- -
- - -
-
-
- - -
- -
- - -
- -
- -
-
-
- -
-
- -
- -
-
-
- -
-
- -
- -
- - -

output


#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm> using namespace std; const double eps = 1e-;
const double PI = acos( -1.0 );
const int MAXN = ; int dcmp( double x ) //控制精度
{
if ( fabs(x) < eps ) return ;
else return x < ? - : ;
} struct Point
{
double x, y;
double ang; //极角
int id;
Point( double x = , double y = ):x(x), y(y) { }
void readPoint()
{
scanf("%lf%lf", &x, &y );
return;
}
void GetAngle()
{
ang = atan2( y, x );
if ( dcmp( ang ) < ) ang = PI + PI+ ang;
return;
}
void showP()
{
printf( "(%.6f, %.6f): ang=%.6f id=%d\n", x, y, ang, id );
return;
}
}; typedef Point Vector; Vector operator+( Vector A, Vector B ) //向量加
{
return Vector( A.x + B.x, A.y + B.y );
} Vector operator-( Vector A, Vector B ) //向量减
{
return Vector( A.x - B.x, A.y - B.y );
} Vector operator*( Vector A, double p ) //向量数乘
{
return Vector( A.x * p, A.y * p );
} Vector operator/( Vector A, double p ) //向量数除
{
return Vector( A.x / p, A.y / p );
} bool operator<( const Point& A, const Point& B ) //两点比较小于
{
return dcmp( A.x - B.x) < || ( dcmp(A.x - B.x ) == && dcmp( A.y - B.y ) < );
} bool operator>( const Point& A, const Point& B ) //两点比较大于
{
return dcmp( A.x - B.x) > || ( dcmp(A.x - B.x ) == && dcmp( 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( Vector A, Vector B ) //向量点乘
{
return A.x * B.x + A.y * B.y;
} double Length( Vector A ) //向量模
{
return sqrt( Dot( A, A ) );
} double Angle( Vector A, Vector B ) //向量夹角
{
return acos( Dot(A, B) / Length(A) / Length(B) );
} double Cross( Vector A, Vector B ) //向量叉积
{
return A.x * B.y - A.y * B.x;
} bool OnSegment( Point p, Point a1, Point a2 ) //点在线段上,不包含端点
{
return dcmp( Cross(a1 - p, a2 - p) ) == && dcmp( Dot( a1 - p, a2 - p ) ) < ;
} int N, M;
Point Poly[MAXN];
int Dcnt; //找到第一个大于的
void BiSearch( double tar, int l, int r, int& u, int& v )
{
//printf("%.6f %.6f %.6f\n", tar, Poly[1].ang, Poly[N].ang );
if ( dcmp( tar - Poly[].ang ) <= || dcmp( tar - Poly[N].ang ) >= )
{
u = N;
v = ;
return;
}
int mid;
int ans = N;
while ( l <= r )
{
mid = ( l + r ) >> ;
if ( dcmp( Poly[mid].ang - tar ) > )
{
ans = mid;
r = mid - ;
}
else l = mid + ;
}
v = ans;
u = v - ;
return;
} bool cmp( Point a, Point b )
{
if ( dcmp( a.ang - b.ang ) != )
return dcmp( a.ang - b.ang ) < ;
return a.id < b.id;
} void init()
{
scanf( "%d%d", &N, &M );
Dcnt = ;
for ( int i = ; i <= N; ++i )
{
Poly[i].readPoint();
Poly[i].GetAngle();
Poly[i].id = i;
}
sort( Poly + , Poly + + N, cmp );
Poly[] = Poly[N];
Poly[].ang -= *PI;
Poly[N+] = Poly[];
Poly[N+].ang += *PI;
return;
} bool check( Point a, Point *p )
{
if ( a == p[] || a == p[] || a == p[] ) return true;
if ( OnSegment( a, p[], p[] ) ) return true;
if ( OnSegment( a, p[], p[] ) ) return true;
if ( OnSegment( a, p[], p[] ) ) return true;
int pre = dcmp( Cross( p[] - p[], a - p[] ) );
for ( int i = ; i < ; ++i )
{
int tmp = dcmp( Cross( p[i + ] - p[i], a - p[i] ) );
if ( tmp != pre ) return false;
}
return true;
} int main()
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T;
scanf( "%d", &T );
while ( T-- )
{
init(); int ans = ;
Point sanjiao[];
sanjiao[] = Point(, );
for ( int i = ; i < M; ++i )
{
Point p;
p.readPoint();
p.GetAngle();
int u, v;
BiSearch( p.ang, , N, u, v );
sanjiao[] = Poly[u];
sanjiao[] = Poly[v];
//printf( "u=%d v=%d\n", u, v );
if ( check( p, sanjiao ) )
{
++ans;
continue;
}
while ( dcmp( Poly[u-].ang - p.ang ) == && u != v )
{
--u;
if ( u == ) u = N;
//printf( "**u=%d v=%d\n", u, v );
sanjiao[] = Poly[u];
sanjiao[] = Poly[v];
if ( check( p, sanjiao ) )
{
++ans;
break;
}
}
}
printf( "%d\n", ans );
}
return ;
}

SPOJ 149 FSHEEP Fencing in the Sheep ( 计算几何 + 二分 )的更多相关文章

  1. 【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流

    题目描述 WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线 ...

  2. 洛谷P3122 [USACO15FEB]圈住牛Fencing the Herd(计算几何+CDQ分治)

    题面 传送门 题解 题目转化一下就是所有点都在直线\(Ax+By-C=0\)的同一侧,也就可以看做所有点代入\(Ax+By-C\)之后的值符号相同,我们只要维护每一个点代入直线之后的最大值和最小值,看 ...

  3. 【POJ】2318 TOYS ——计算几何+二分

    TOYS Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10281   Accepted: 4924 Description ...

  4. BZOJ_1020_[SHOI2008]_安全的航线flight_(计算几何+二分)

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1020 给出一条航线(折线),给出\(c\)个陆地(多边形).求航线上距离陆地的最近距离最远的距 ...

  5. hdu 4033 Regular Polygon 计算几何 二分+余弦定理

    题目链接 给一个n个顶点的正多边形, 给出多边形内部一个点到n个顶点的距离, 让你求出这个多边形的边长. 二分边长, 然后用余弦定理求出给出的相邻的两个边之间的夹角, 看所有的加起来是不是2Pi. # ...

  6. 牛客第二场 C.message(计算几何+二分)

    题目传送:https://www.nowcoder.com/acm/contest/140/C 题意:有n个云层,每个云层可以表示为y=ax+b.每个飞机的航线可以表示为时间x时,坐标为(x,cx+d ...

  7. hdu 3264 09 宁波 现场 E - Open-air shopping malls 计算几何 二分 圆相交面积 难度:1

    Description The city of M is a famous shopping city and its open-air shopping malls are extremely at ...

  8. HDU 3264/POJ 3831 Open-air shopping malls(计算几何+二分)(2009 Asia Ningbo Regional)

    Description The city of M is a famous shopping city and its open-air shopping malls are extremely at ...

  9. Codeforces gym102058 J. Rising Sun-简单的计算几何+二分 (2018-2019 XIX Open Cup, Grand Prix of Korea (Division 2))

    J. Rising Sun time limit per test 1.0 s memory limit per test 1024 MB input standard input output st ...

随机推荐

  1. 文本编辑器Vim技巧

    1.  导入文件内容  :r  文件名 2.  插入当前日期  :r  !date 3. :!which ls 4. :r !命令

  2. 线程池,多线程,线程异步,同步和死锁,Lock接口

    线程池 线程池,其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源. 除了创建和销毁线程的开销之外,活动的线程也需要消耗系统资源.线程 ...

  3. java斗地主扑克 扑克牌 洗牌 发牌 Collection 集合练习

    package com.swift.poker; import java.util.ArrayList; import java.util.Collections; /*训练考核知识点:Collect ...

  4. 调整JVM占用内存空间方法

    JVM默认占用空间为64M 调整方法如下图 在虚拟机参数中调整为80M 调试可以用 Byte[] arr=new Byte[1024*1024*64];

  5. 开发常用宏 - iOS

    以下是一些开发中会经常用到的宏,简单的进行了整理,为了今后可以更加方便的使用,从而提升开发的效率,不为此搭进去更多时间. 也希望有大家可以补充,从而使其更加强加! /** * 开发常用宏相关 */ # ...

  6. 3.2.5 Magic Squares 魔板

    3.2.5 Magic Squares 魔板 成功地发明了魔方之后,鲁比克先生发明了它的二维版本,称作魔板.这是一张有8个大小相同的格子的魔板: 1 2 3 4 8 7 6 5 我们知道魔板的每一个方 ...

  7. BZOJ1202: [HNOI2005]狡猾的商人(带权并查集)

    Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4577  Solved: 2249[Submit][Status][Discuss] Descript ...

  8. spring-传统AOP

    Spring传统AOP AOP的增强类型 AOP联盟定义了Advice(org.aopalliance.aop.Interface.Advice) 五类(目标类方法的连接点): 1.  前置通知(or ...

  9. 正则表达式re.S的用法

    正则表达式re.S的用法 在Python的正则表达式中,有一个参数为re.S.它表示"."(不包含外侧双引号,下同)的作用扩展到整个字符串,包括"\n".看如下 ...

  10. 【Effective C++ 读书笔记】条款03: 尽量使用 const

    关键字const多才多艺,变化多端却不高深莫测. const 修饰指针 面对指针, 你可以指出 指针自身.指针所指物.或者两者都不是 const. 如果关键字 const 出现在星号左边,表示被指物是 ...