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. 锋利的jQuery第2版学习笔记1~3章

    第1章,认识jQuery 注意:使用的jQuery版本为1.7.1 目前流行的JavaScript库 Prototype(http://www.prototypejs.org),成型早,面向对象的思想 ...

  2. MySqlDataReader在Using中使用

    结论:当DataReader放在Using方法中时,会自动释放资源,如果中途出现了异常处理,也同样会释放掉占用的资源.测试过程:这里由于没有将全部分过程记录下来,只是对结果大体的说明一下,有兴趣的童鞋 ...

  3. Jersey(1.19.1) - Client API, Uniform Interface Constraint

    The Jersey client API is a high-level Java based API for interoperating with RESTful Web services. I ...

  4. Git - Download for Linux and Unix

    It is easiest to install Git on Linux using the preferred package manager of your Linux distribution ...

  5. .net System.Net.Mail 之用SmtpClient发送邮件 Demo

    private static bool sendMail() { try { //接收人邮箱 string SendTo = "XXXXX@163.com"; //抄送人邮箱 st ...

  6. JAVA计算器算法实现

    import java.awt.BorderLayout; import java.awt.GridLayout; import java.awt.event.ActionEvent; import ...

  7. web服务器顺带网络负载均衡

    Web服务器配置共享文件 文件服务器需要做的 1. 建立共享文件夹,并建立两个子文件夹 2. 创建用户以便访问共享时使用此凭据 3. 共享并给予刚创建的用户读取和写入权限 Web服务器的设置 1. 新 ...

  8. Kill Session

    有时候创建索引或修改表字段时,会提示资源正忙,可以查出表对应的进程并kill掉 select l.session_id,o.owner,o.object_name from v$locked_obje ...

  9. FreeCodeCamp-JS基础部分

    ---恢复内容开始--- .pop()     将数组末尾的元素移除     var removedFromMyArray=myArray.pop()     将myArray数组的最后一个元素移除并 ...

  10. java filter的一些理解

    java filter即  java中的过滤器: 一. * web项目中只有三个组件 * 过滤器filter  ↓    级 别 * 监听器            ↓   级 别 * servlet  ...