Description

在设计航线的时候,安全是一个很重要的问题。首先,最重要的是应采取一切措施确保飞行不会发生任何事故,但同时也需要做好最坏的打算,一旦事故发生,就要确保乘客有尽量高的生还几率。当飞机迫降到海上的时候,最近的陆地就是一个关键的因素。航线中最危险的地方就是距离最近的陆地最远的地方,我们称这种点为这条航线“孤地点”。孤地点到最近陆地的距离被称为“孤地距离”。作为航空公司的高级顾问,你接受的第一个任务就是尽量找出一条航线的孤地点,并计算这条航线的孤地距离。为了简化问题,我们认为地图是一个二维平面,陆地可以用多边形近似,飞行线路为一条折线。航线的起点和终点都在陆地上,但中间的转折点是可能在海上(如下图所示,方格标示出了孤地点)。
Input

输入的第一行包括两个整数C和N(1≤C≤20,2≤N≤20),分别代表陆地的数目的航线的转折点的数目。接下来有N行,每行有两个整数x,y。(x,y)表示一个航线转折点的坐标,第一个转折点为航线的起点,最后一个转折点为航线的终点。接下来的输入将用来描述C块大陆。每块输入由一个正整数M开始(M≤30),M表示多边形的顶点个数,接下来的M行,每行会包含两个整数x,y,(x,y)表示多边形的一个顶点坐标,我们保证这些顶点以顺时针或逆时针给出了该多边形的闭包,不会出现某些边相交的情况。此外我们也保证输入数据中任何两块大陆不会相交。输入的所有坐标将保证在-10000到10000的范围之间。
Output

输出一个浮点数,表示航线的孤地距离,数据保留2位小数。
Sample Input
1 2
-9 -6
5 1
3
0 16
-16 -12
17 -6
Sample Output
0.00

原来的解法是二分答案,然后把陆地扩展,再判断是否覆盖了航线,但是太繁琐,我根本写不出来

所以我用的是莫涛的那种解法

没想到我竟然错在求垂足上,囧..........

但是答案竟然正确了,时间变长了好多,查了好久才查出来

1.初始化孤地点可能位于的线段集合为整条航线。
2.对于长L的某条线段,左端点与陆地的最近点为P1,右端点与陆地的最近点为P2,那么该线段上的孤地距离将受P1与P2影响。具体来说,利用二分求出该线段上的点P使得dis(p1,p)=dis(p2,p)
令r=dis(p1,p),若r小于已有的最优答案,那么可以删除该线段。(当然,这个只要r-0.001<ans就行了,只要精度达到了就行,不然就是死循环了)
4.取所有线段的中点更新答案。
5.将所有线段从中点分成左右两条线段。
6.不断进行2,3,4直到线段的集合为空。

这个做法效率很高,(哇,好开心,在BZOJ上是pascal第一)

我们现在要讨论的就是这个算法的正确性

现在我们有一条线段和对应的p1和p2,分别是左端点最近的点和右端点最近的点

有三种情况

然后我们发现线段上的点到自己最近点的距离不会超过max(dis(p1,p),dis(a,p1),(b,p2))(a,b分别为线段的左右端点)

所以我们的删除操作是对的,我们删除的都是不会更新答案的线段,就像ydc说的一样,这个就像是搜索剪枝

时间效率也很好,只是细节要注意,不要像我一样傻×,连求垂足都求错

 /**************************************************************
Problem:
User: 1997cb
Language: Pascal
Result: Accepted
Time: ms
Memory: kb
****************************************************************/ const
maxn=;
maxm=;
maxq=;
eps=1e-16;
type
point=record
x,y:double;
end;
polygon=record
tot:longint;
a:array[..maxm]of point;
end;
seg=record
a,b,neara,nearb:point;
end;
var
c,head,tail:longint;
ans:double;
s:array[..maxq]of seg;
p:array[..maxn]of polygon; function max(x,y:double):double;
begin
if x>y then exit(x);
exit(y);
end; function cj(x1,y1,x2,y2:double):double;
begin
exit(x1*y2-y1*x2);
end; function on(var a,b,c:point):boolean;
begin
exit((abs(cj(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y))<=eps) and ((a.x-c.x)*(b.x-c.x)<=eps) and ((a.y-c.y)*(b.y-c.y)<=eps));
end; function jiao(var a,b,c,d:point):boolean;
begin
exit((cj(b.x-a.x,b.y-a.y,d.x-a.x,d.y-a.y)*cj(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y)<=eps) and (cj(d.x-c.x,d.y-c.y,a.x-c.x,a.y-c.y)*cj(d.x-c.x,d.y-c.y,b.x-c.x,b.y-c.y)<=eps));
end; function include(var a:polygon;var b:point):boolean;
var
i,tot:longint;
k:point;
begin
for i:= to a.tot do
if on(a.a[i],a.a[i mod a.tot+],b) then exit(true);
tot:=;
k.x:=-;
k.y:=;
for i:= to a.tot do
if jiao(a.a[i],a.a[i mod a.tot+],k,b) then inc(tot);
if tot and = then exit(true);
exit(false);
end; procedure get(var near,a:point;var dis:double;var b,c:point);
var
d:double;
begin
if (c.x-b.x)*(a.x-b.x)+(c.y-b.y)*(a.y-b.y)<=eps then
begin
d:=sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
if dis>d+eps then
begin
near:=b;
dis:=d;
end;
exit;
end;
if (c.x-b.x)*(a.x-c.x)+(c.y-b.y)*(a.y-c.y)>=-eps then
begin
d:=sqrt(sqr(a.x-c.x)+sqr(a.y-c.y));
if dis>d+eps then
begin
near:=c;
dis:=d;
end;
exit;
end;
d:=cj(c.x-b.x,c.y-b.y,a.x-b.x,a.y-b.y)/sqrt(sqr(b.x-c.x)+sqr(b.y-c.y));
if dis>abs(d)+eps then
begin
dis:=abs(d);
near.x:=a.x+(c.y-b.y)*d/sqrt(sqr(b.x-c.x)+sqr(b.y-c.y));
near.y:=a.y-(c.x-b.x)*d/sqrt(sqr(b.x-c.x)+sqr(b.y-c.y));
end;
end; procedure find(var a,b:point);
var
i,j:longint;
dis:double;
begin
for i:= to c do
if include(p[i],b) then
begin
a:=b;
exit;
end;
dis:=<<;
for i:= to c do
for j:= to p[i].tot do
get(a,b,dis,p[i].a[j],p[i].a[j mod p[i].tot+]);
ans:=max(ans,dis);
end; procedure init;
var
i,j:longint;
begin
read(c,tail);
head:=;
for i:= to tail do
with s[i].a do
read(x,y);
for i:= to c do
with p[i] do
begin
read(tot);
for j:= to tot do
with a[j] do
read(x,y);
end;
for i:= to tail do
with s[i] do
find(neara,a);
for i:= to tail- do
begin
s[i].b:=s[i+].a;
s[i].nearb:=s[i+].neara;
end;
end; procedure work;
var
l,r,mid:point;
d:double;
begin
while head<>tail do
begin
l:=s[head].a;
r:=s[head].b;
while (sqrt(sqr(l.x-r.x)+sqr(l.y-r.y))>1e-4) do
begin
mid.x:=(l.x+r.x)/;
mid.y:=(l.y+r.y)/;
with s[head] do
if sqrt(sqr(mid.x-neara.x)+sqr(mid.y-neara.y))<sqrt(sqr(mid.x-nearb.x)+sqr(mid.y-nearb.y)) then l:=mid
else r:=mid;
end;
with s[head] do
d:=max(sqrt(sqr(l.x-neara.x)+sqr(l.y-neara.y)),sqrt(sqr(l.x-nearb.x)+sqr(l.y-nearb.y)));
mid.x:=(s[head].a.x+s[head].b.x)/;
mid.y:=(s[head].a.y+s[head].b.y)/;
find(l,mid);
if d>ans+0.001 then
begin
s[tail].a:=s[head].a;
s[tail].b:=mid;
s[tail].nearb:=l;
s[tail].neara:=s[head].neara;
tail:=tail mod maxq+;
s[tail].a:=mid;
s[tail].b:=s[head].b;
s[tail].neara:=l;
s[tail].nearb:=s[head].nearb;
tail:=tail mod maxq+;
end;
head:=head mod maxq+;
end;
write(ans::);
end; begin
init;
work;
end.

1020: [SHOI2008]安全的航线flight - BZOJ的更多相关文章

  1. BZOJ 1020 [SHOI2008]安全的航线flight

    1020: [SHOI2008]安全的航线flight Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 847  Solved: 286[Submit][ ...

  2. 【BZOJ 1020】 [SHOI2008]安全的航线flight

    [题目链接]:http://www.lydsy.com/JudgeOnline/problem.php?id=1020 [题意] [题解] 二分+判断点是否在多边形区域内+计算点到直线的最短距离 对于 ...

  3. 【BZOJ】【1020】【SHOI2008】安全的航线flight

    计算几何/二分/迭代/搜索+剪枝 写三个tag可能是因为从哪个方向来理解都可以吧…… 我完全不会计算几何所以抄了ydc的代码 题解:http://ydcydcy1.blog.163.com/blog/ ...

  4. BZOJ 1020 安全的航线flight

    Description 在设计航线的时候,安全是一个很重要的问题.首先,最重要的是应采取一切措施确保飞行不会发生任何事故,但同时也需要做好最坏的打算,一旦事故发生,就要确保乘客有尽量高的生还几率.当飞 ...

  5. 1021: [SHOI2008]Debt 循环的债务 - BZOJ

    Description Alice.Bob和Cynthia总是为他们之间混乱的债务而烦恼,终于有一天,他们决定坐下来一起解决这个问题.不过,鉴别钞票的真伪是一件很麻烦的事情,于是他们决定要在清还债务的 ...

  6. 1018: [SHOI2008]堵塞的交通traffic - BZOJ

    Description 有一天,由于某种穿越现象作用,你来到了传说中的小人国.小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一 ...

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

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

  8. 怒刷BZOJ记录(一)1001~1037

    我实在是太弱了...不滚粗只能刷BZOJ了...这里来记录每天刷了什么题吧. 2015-7-9 : 1001[BeiJing2006]狼抓兔子                 | 最大流练习(呃..其 ...

  9. BZOJ练习记

    决定从头到尾干一波BZOJ!可能会写没几题就停下吧,但还是想学学新姿势啦. 1001. [BeiJing2006]狼抓兔子 即求 $(1, 1)$ 到 $(n, m)$ 的最小割.跑 dinic 即可 ...

随机推荐

  1. 实用工具推荐(Live Writer)(2015年05月26日)

    1.写博客的实用工具 推荐软件:Live Writer 使用步骤: 1.安装 Live Essential 2011,下载地址:http://explore.live.com/windows-live ...

  2. spring+mybatis管理多个数据源(非分布式事务)

    本文通过一个demo,介绍如何使用spring+mybatis管理多个数据源,注意,本文的事务管理并非之前博文介绍的分布式事务. 这个demo将使用两个事务管理器分别管理两个数据源.对于每一个独立的事 ...

  3. .net转java了

    公司技术部门  要求.net全体转向java 本来要看看.net core的 看来是没必要了  现在国内互联网公司.net是越来越少  不知道为何会这样 不过java的生态圈 确实是很强大 也很丰富 ...

  4. (转)Salesforce的440亿美金并购宣告企业软件市场进入3.0互联网化时代

    导语:Salesforce代表着“移动+云”时代企业软件领域新的架构和商业模式的颠覆者.企业软件转向“移动+云”架构,将极大改变传统企业IT市场的格局…… 近期一则新闻极大的刺激了企业软件市场的神经, ...

  5. 通过Curator操作Zookeeper的简单例子代码

    Curator主要解决了三类问题: 一个是ZooKeeper client与ZooKeeper server之间的连接处理; 一个是提供了一套Fluent风格的操作API; 一个是ZooKeeper各 ...

  6. 《大话设计模式》学习笔记0:设计模式的原则 && UML类图

    一.单一职责原则:就一个类而言,应该仅有一个引起它变化的原因. 如果一个类承担的职责过多,就等于把这些职责耦合在一起,一个职责的变化可能会削弱或者抑制这个类完成其他职责的能力.这种耦合会导致脆弱的设计 ...

  7. L005-oldboy-mysql-dba-lesson05

    L005-oldboy-mysql-dba-lesson05 在线改表工具:pt-onine-schema-change 来自为知笔记(Wiz)

  8. CSS的引入方式

    再用HTML编写的文本中,有是没能达到我们想要的效果,此时此刻我们可以用过引用CSS来控制!这不仅使得效果好而且代码层次清晰.CSS的引入方式可以分为四类: 1.链入外部样式表,就是把样式表保存为一个 ...

  9. Android 控件收集

    SwipeMenuExpandableListView   https://github.com/tycallen/SwipeMenu-Expandable-ListView

  10. mongo数据库基础操作

    概念 一个mongod服务可以有建立多个数据库,每个数据库可以有多张表,这里的表名叫collection,每个collection可以存放多个文档(document),每个文档都以BSON(binar ...