SPOJ 149 FSHEEP Fencing in the Sheep ( 计算几何 + 二分 )
以下摘自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 ( 计算几何 + 二分 )的更多相关文章
- 【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流
题目描述 WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线 ...
- 洛谷P3122 [USACO15FEB]圈住牛Fencing the Herd(计算几何+CDQ分治)
题面 传送门 题解 题目转化一下就是所有点都在直线\(Ax+By-C=0\)的同一侧,也就可以看做所有点代入\(Ax+By-C\)之后的值符号相同,我们只要维护每一个点代入直线之后的最大值和最小值,看 ...
- 【POJ】2318 TOYS ——计算几何+二分
TOYS Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 10281 Accepted: 4924 Description ...
- BZOJ_1020_[SHOI2008]_安全的航线flight_(计算几何+二分)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1020 给出一条航线(折线),给出\(c\)个陆地(多边形).求航线上距离陆地的最近距离最远的距 ...
- hdu 4033 Regular Polygon 计算几何 二分+余弦定理
题目链接 给一个n个顶点的正多边形, 给出多边形内部一个点到n个顶点的距离, 让你求出这个多边形的边长. 二分边长, 然后用余弦定理求出给出的相邻的两个边之间的夹角, 看所有的加起来是不是2Pi. # ...
- 牛客第二场 C.message(计算几何+二分)
题目传送:https://www.nowcoder.com/acm/contest/140/C 题意:有n个云层,每个云层可以表示为y=ax+b.每个飞机的航线可以表示为时间x时,坐标为(x,cx+d ...
- 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 ...
- 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 ...
- 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 ...
随机推荐
- java多线程同步以及线程间通信详解&消费者生产者模式&死锁&Thread.join()(多线程编程之二)
本篇我们将讨论以下知识点: 1.线程同步问题的产生 什么是线程同步问题,我们先来看一段卖票系统的代码,然后再分析这个问题: package com.zejian.test; /** * @author ...
- 由fastRPC产生的DB服务
根据整理的RPC模型,在此上,根据最近的项目,发布了DB服务,操作数据库.以RPC模型,发布数据库的操作服务,主要发送SQL语句,在服务端执行:同时引入了流行的数据库连接池:服务端还发布了文件接收服务 ...
- scoped,会使设置UI组件库的样式识别不出来
未设置 scoped 作用域:显示效果 设置作用域的效果:ui组件默认的值(你怎么设置都不管用)
- LeetCode804. Unique Morse Code Words
题目 国际摩尔斯密码定义一种标准编码方式,将每个字母对应于一个由一系列点和短线组成的字符串, 比如: "a" 对应 ".-", "b" 对应 ...
- js jquery 权限单选 bug修改以及正确代码 购物车数量加减
效果图废话不多直接上代码 用的avalon渲染,其实都是一样的 <div class="shop-arithmetic"> <a href="javas ...
- django+xadmin在线教育平台(十二)
6-4 用form实现登录-1 上面我们的用户登录的方法是基于函数来做的.本节我们做一个基于类方法的版本. 要求对类的继承有了解. 基础教程中基本上都是基于函数来做的,其实更推荐基于类来做.基于类可以 ...
- js | javascript中获取dom元素的高度和宽度
javascript中获取dom元素高度和宽度的方法如下: 网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网 ...
- python中的文件操作小结1
#!/usr/local/bin/python3 # -*- coding:utf-8 -*- f=open("test_1",'r',encoding="utf-8&q ...
- 编辑工具_vi
vi/vim平时经常会用到,但是一直没有时间系统的整理下,今天看到了一篇不错的介绍文章.引用下,就当做笔记了,但是不晓得该怎么填引用路径,如有侵权请告知,补上引用路径 01. vi 简介 1.1 学习 ...
- 一个操作轻松截取长图,Win10上网截长图小技巧!
截屏的方法有很多,但是有时候我们会遇到比电脑屏幕还大的图,比如网站上的长图.N条引用的评论...你要怎么截取呢?是不是最多只能截全屏?还是要做到第三方的截图软件呢? 下面介绍一种win10电脑自带的滚 ...