BZOJ 1137: [POI2009]Wsp 岛屿 半平面交
1137: [POI2009]Wsp 岛屿
Time Limit: 10 Sec Memory Limit: 162 MBSec Special Judge
Submit: 165 Solved: 78
[Submit][Status][Discuss]
Description
Byteotia岛屿是一个凸多边形。城市全都在海岸上。按顺时针编号1到n。任意两个城市之间都有一条笔直的道路相连。道路相交处可以自由穿行。有一些道路被游击队控制了,不能走,但是可以经过这条道路与未被控制的道路的交点。问从城市1到n的最短距离。
Input
第一行正整数n m表示城市数和被控制的岛屿数(3≤n≤10^5 1≤m≤10^6)接下来n行每行两个整数x y表示每个城市的坐标。(|x|,|y|≤10^6)接下来m行描述一条不能走的道路(起点和终点)。数据保证有解。
Output
输出一个实数,最短距离,误差10^-5以内均算正确。
Sample Input
-12 -10
-11 6
-4 12
6 14
16 6
18 -2
3 4
1 5
2 6
2 3
4 5
3 5
1 3
3 6
1 6
Sample Output
HINT
Source
#include<cmath>
#include<cstdio>
#include<vector>
#include<algorithm> const int len();
const double eps(1e-);
struct Coor//向量或点
{
double x,y;
Coor(){};
Coor(double a,double b):x(a),y(b){};
inline Coor operator +(const Coor&a)const{return Coor(x+a.x,y+a.y);}
inline Coor operator -(const Coor&a)const{return Coor(x-a.x,y-a.y);}
inline Coor operator *(const double&k)const{return Coor(x*k,y*k);}
inline Coor operator /(const double&k)const{return Coor(x/k,y/k);}
}pr[len+],ie[len+];int tot;
double dot(Coor a,Coor b){return a.x*b.x+a.y*b.y;}//点积
double cross(Coor a,Coor b){return a.x*b.y-a.y*b.x;}//叉积
struct Line
{
Coor a,b;//直线上两个点a->b,钦点半平面交均保留向量左手方向。
double angle;
Line(){};
Line(Coor A,Coor B,double a):a(A),b(B),angle(a){};
Coor intersect(Line &B)
{
double s1=cross(B.a-a,B.b-a),s2=cross(B.b-b,B.a-b);//面积的方向
return a+(b-a)*s1/(s1+s2);
}
void getAngle(){angle=atan2(b.y-a.y,b.x-a.x);}
}L[len+];int up;
int n,m,x,y;long double ans;
std::vector<int>Edge[len+];
void swap(int &x,int &y){x^=y,y^=x,x^=y;}
int dcmp(double x){return x<-eps?-:x>eps;}
bool cmp(Line A,Line B)
{
double c=A.angle-B.angle;
int d=dcmp(c);
if(d)return d>;//逆时针,事实证明这里正着反着都一样。
c=cross(A.b-A.a,B.b-A.a);//保留左手方向
return c<-eps;
}
bool jud(Line p1,Line p2,Line p3)
{
Coor p=p1.intersect(p2);
double c=cross(p3.b-p3.a,p-p3.a);
return dcmp(c)<;
}
void deal()
{
int _up=;
for(int i=;i<=up;i++)if(dcmp(L[i-].angle-L[i].angle))L[++_up]=L[i];
up=_up;
}
long double sqr(long double x){return x*x;}
long double dis(Coor A,Coor B)
{
return sqrt(sqr(A.x-B.x)+sqr(A.y-B.y));
}
int que[len+],head,tail;
void SI()
{
std::sort(L+,L++up,cmp);//排序可能会打乱顺序
deal();
que[]=;que[]=;head=;tail=;
for(int i=;i<=up;i++)
{
while(head<tail && jud(L[que[tail-]],L[que[tail]],L[i]))
tail--;
while(head<tail && jud(L[que[head+]],L[que[head]],L[i]))
head++;
que[++tail]=i;
}
while(head<tail- && jud(L[que[tail-]],L[que[tail]],L[que[head]]))
tail--;
while(head+<tail && jud(L[que[head+]],L[que[head]],L[que[tail]]))
head++;
que[tail+]=que[head];
for(int i=head;i<=tail;i++)ie[++tot]=L[que[i]].intersect(L[que[i+]]);
ie[tot+]=ie[];
for(int i=;i<=tot;i++)ans+=dis(ie[i],ie[i+]);
ans-=dis(pr[],pr[n]);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)scanf("%lf %lf",&pr[i].x,&pr[i].y);
for(int i=;i<=m;i++)
{
scanf("%d %d",&x,&y);
if(x>y)swap(x,y);
Edge[x].push_back(y);
}
for(int i=,j;i<n;i++)
{
std::sort(Edge[i].begin(),Edge[i].end());
j=n;
while(Edge[i].size()&&Edge[i].back()==j&&j>i)
j--,Edge[i].pop_back();
if(j>i)L[++up]=Line(pr[j],pr[i],);//逆时针
if(i==&&j==n)ans=dis(pr[],pr[n]);
}
if(ans){printf("%.10Lf\n",ans);return ;}
L[++up]=Line(pr[],pr[n],);
for(int i=;i<=up;i++)L[i].getAngle();
SI();
printf("%.10Lf\n",ans);
return ;
}
BZOJ 1137: [POI2009]Wsp 岛屿 半平面交的更多相关文章
- bzoj 1137 [POI2009]Wsp 岛屿
题目大意 Byteotia岛屿是一个凸多边形.城市全都在海岸上.按顺时针编号1到n.任意两个城市之间都有一条笔直的道路相连.道路相交处可以自由穿行.有一些道路被游击队控制了,不能走,但是可以经过这条道 ...
- BZOJ 1038 ZJOI2008 瞭望塔 半平面交
题目大意及模拟退火题解:见 http://blog.csdn.net/popoqqq/article/details/39340759 这次用半平面交写了一遍--求出半平面交之后.枚举原图和半平面交的 ...
- bzoj 4445 小凸想跑步 - 半平面交
题目传送门 vjudge的快速通道 bzoj的快速通道 题目大意 问在一个凸多边形内找一个点,连接这个点和所有顶点,使得与0号顶点,1号顶点构成的三角形是最小的概率. 假设点的位置是$(x, y)$, ...
- bzoj 3190 赛车 半平面交
直接写的裸的半平面交,已经有点背不过模板了... 这题卡精度,要用long double ,esp设1e-20... #include<iostream> #include<cstd ...
- BZOJ 4445 [Scoi2015]小凸想跑步:半平面交
传送门 题意 小凸晚上喜欢到操场跑步,今天他跑完两圈之后,他玩起了这样一个游戏. 操场是个凸 $ n $ 边形,$ n $ 个顶点 $ P_i $ 按照逆时针从 $ 0 $ 至 $ n-1 $ 编号. ...
- BZOJ 1829 [Usaco2010 Mar]starc星际争霸 ——半平面交
发现最终的结果只和$s1$,$s2$,$s3$之间的比例有关. 所以直接令$s3=1$ 然后就变成了两个变量,然后求一次半平面交. 对于每一个询问所属的直线,看看半平面在它的那一侧,或者相交就可以判断 ...
- 【BZOJ-4515】游戏 李超线段树 + 树链剖分 + 半平面交
4515: [Sdoi2016]游戏 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 304 Solved: 129[Submit][Status][ ...
- poj3335 半平面交
题意:给出一多边形.判断多边形是否存在一点,使得多边形边界上的所有点都能看见该点. sol:在纸上随手画画就可以找出规律:按逆时针顺序连接所有点.然后找出这些line的半平面交. 题中给出的点已经按顺 ...
- POJ3525 半平面交
题意:求某凸多边形内部离边界最远的点到边界的距离 首先介绍半平面.半平面交的概念: 半平面:对于一条有向直线,它的方向的左手侧就是它所划定的半平面范围.如图所示: 半平面交:多个半平面的交集.有点类似 ...
随机推荐
- php array数组(第一部分)
创建一个数组 <?php $arr = array("My","name","is","zhangsan"); e ...
- Ubuntu 14.04中修复默认启用HDMI后没有声音的问题
声音问题在Ubuntu中是老生常谈了.先前我已经在修复Ubuntu中的“无声”问题一文中写到了多种方法,但是我在此正要谈及的声音问题跟在另外一篇文章中提到的有所不同. 因此,我安装了Ubuntu 14 ...
- ue4 模拟tween
timeline的设置,注意timeLine可以使用外部的曲线,这个比较方便做各种曲线,timeline内部只适合打单个点
- JS 上拉加载
$(document).ready( function(){ $contentLoadTriggered = false; $("#mainDiv").scroll(functio ...
- tarjan求割点割边的思考
这个文章的思路是按照这里来的.这里讨论的都是无向图.应该有向图也差不多. 1.如何求割点 首先来看求割点.割点必须满足去掉其以后,图被分割.tarjan算法考虑了两个: 根节点如果有两颗及以上子树,它 ...
- 洛谷 P2327 [SCOI2005]扫雷
P2327 [SCOI2005]扫雷 https://www.luogu.org/problem/show?pid=2327 题目描述 输入输出格式 输入格式: 第一行为N,第二行有N个数,依次为第二 ...
- c语言的小问题
在c语言编程中要注意一个小问题,如果你编写scanf("%d",&n);printf("%d",n)这个你输入几就输出几,毫无疑问.但是现在问题来了?如 ...
- 8.Python初窥门径(文件操作)
Python (文件操作) 一.文件操作方式 打开文件 open 操作文件 read or write 关闭文件 close 二.打开文件的方式(第一种) 语法 : f=open("文件&q ...
- Linux常用命令(补充)-grep
grep(global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具,它能使用正 ...
- Centos下安装pip失败或新装
Centos安装pip失败: [root@localhost /]# yum -y install pip已加载插件:fastestmirrorRepodata is over 2 weeks old ...