以下摘自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. MongoDB在MFC下使用C++驱动编译错误的解决

    .post p{text-indent: 2em;} 今天使用MongoDB的C++驱动,在编译连接的时候一直出现错误,显示的string_data.h下93行max宏的问题,可视其本身并不是调用ma ...

  2. python的**和*

    1.**两个乘号就是乘方,比如2**4,结果就是2的4次方,结果是16一个乘号*,如果操作数是两个数字,就是这两个数字相乘,如2*4,结果为8*如果是字符串.列表.元组与一个整数N相乘,返回一个其所有 ...

  3. java多线程同步以及线程间通信详解&消费者生产者模式&死锁&Thread.join()(多线程编程之二)

    本篇我们将讨论以下知识点: 1.线程同步问题的产生 什么是线程同步问题,我们先来看一段卖票系统的代码,然后再分析这个问题: package com.zejian.test; /** * @author ...

  4. 交换机基础配置之stp生成树实验

    实验的要求是以上面的拓扑图为例,查看当前根桥的所在并把三成交换机switch1指定为根桥 我们可以用show spanning-tree来查看stp的信息 输入后会显示两部分 上面一部分为当前交换机自 ...

  5. 【CodeBase】PHP将数组键名转成变量名

    <?php /** * php 把数组中的键名所为变量名键值作为变量名 */ $arr=array('a'=>1,'b'=>2,'c'=>3,'d'=>5,'e'=> ...

  6. 在程序开发中,++i 与 i++的区别

    在不参与运算的情况下,i++和++i都是在变量的基础加1 ◆在参与运算的情况下 Var i=123; Var j=i++;  先将i的值123赋值给j,之后再自增 j的值为123  i 的值为124 ...

  7. Python全栈day 01

    Python全栈day 01 一.计算机认识 用户 软件,类似微信.QQ.游戏等应用程序,由程序员编写,在系统中运行,完成各种活动,方便人们使用. 操作系统,主要分为windows系统.Linux系统 ...

  8. Windows Server 远程桌面连接不上问题解决

    关于Windows Server 远程桌面连接不上的问题需要从服务.端口.防火墙这几方面进行检查: 服务器上需要 开启的服务: - Remote Access Auto Connection Mana ...

  9. 15.5,centos下redis安全相关

      博文背景: 由于发现众多同学,在使用云服务器时,安装的redis3.0+版本都关闭了protected-mode,因而都遭遇了挖矿病毒的攻击,使得服务器99%的占用率!! 因此我们在使用redis ...

  10. getElementByName????????,????????,

    getElementByName可以获取多个元素,获得的是一个数组, getElementById只能获取一个,是dom从上往下的第一个元素.