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
吐槽:不得不说这种计算几何题TTM恶心了,对着数据(70个点用geogebra一一手打)调了3天。功夫不负有心人,还是切掉了。感谢我们学校的大神犇莫涛学长的算法,不然像我这种蒟蒻恐怕一辈子都写不出二分答案的正解。
为了表示膜拜,我将我的做法口述一遍吧(其实就是莫涛学长在论文上写的那种迭代),忽然间感觉自己和ydc比起来写得好丑。
  1. 先将所有不在多边形内部的线段加入队列中;
  2. 取出队首线段,找出与左端点最近的多边形上的点p1,右端点最近的多边形上的点p2。ans = max(ans,dis(p1,左端点),dis(p2,右端点));
  3. 在线段上二分出一个点p,使得dis(p,p1) == dis(p,p2);
  4. 若dis(p,p1) < ans,continue;否则,将线段二等分加入队列中;
  5. 重复2,3,4直到队列为空;

算法(减枝)就是这样。为什么这样是对的呢?我们证明一下:

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

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

有三种情况

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

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

(注:上述证明转自:http://www.cnblogs.com/Randolph87/p/3642917.html)

最后再贴一份自己丑丑的代码:

  1 #include<algorithm>
  2 #include<cmath>
  3 #include<queue>
  4 #include<cstdio>
  5 #include<cstdlib>
  6 #include<iostream>
  7 using namespace std;
  8
  9 #define rhl 10001
 10 #define esp (1e-4)
 11 #define maxn (30)
 12 #define maxc (30)
 13 #define maxm (40)
 14 int tot,n,c,have[maxc]; double ans;
 15
 16 inline double equal(double a,double b) { return fabs(a-b) < esp; }
 17
 18 inline bool dd(double a,double b) { if (equal(a,b)) return true; return a >= b; }  //>=
 19
 20 inline bool xd(double a,double b) { if (equal(a,b)) return true; return a <= b; }  //<=
 21
 22 struct NODE
 23 {
 24     double x,y;
 25     friend inline bool operator == (NODE a,NODE b) { return equal(a.x,b.x)&&equal(a.y,b.y); }
 26     friend inline bool operator < (NODE a,NODE b)
 27     {
 28         if (a.x != b.x) return a.x < b.x;
 29         else return a.y < b.y;
 30     }
 31     inline NODE ra()
 32     {
 33         int xx,yy;
 34         do xx = rand()%rhl,yy = rand()%rhl;
 35         while (equal(1.0*xx,x)||equal(1.0*yy,y));
 36         return (NODE) {1.0*xx,1.0*yy};
 37     }
 38     inline void read() { scanf("%lf %lf",&x,&y); }
 39 }pol[maxc][maxm],bac[maxc*maxm];
 40 struct LINE
 41 {
 42     double a,b,c;
 43     friend inline bool operator ==(LINE l1,LINE l2) { return equal(l1.a*l2.c,l2.a*l1.c); }
 44     inline LINE vert(NODE p) { return (LINE) {b,-a,a*p.y-b*p.x}; }
 45     inline bool on(NODE p) { return equal(0,a*p.x+b*p.y+c); }
 46 };
 47 struct SEG{
 48     NODE a,b;
 49     inline NODE MID() { return (NODE) {(a.x+b.x)/2,(a.y + b.y)/2}; }
 50     inline bool exist() { return !(a == b); }
 51     inline LINE extend() { return (LINE) {a.y-b.y,b.x-a.x,b.y*(a.x-b.x)-b.x*(a.y-b.y)}; }
 52     inline bool on(NODE p)
 53     {
 54         if (p == a) return true;
 55         if (p == b) return true;
 56         return (dd(p.x,min(a.x,b.x))&xd(p.x,max(a.x,b.x)))&&(dd(p.y,min(a.y,b.y))&xd(p.y,max(a.y,b.y)));
 57     }
 58 }temp[maxn];
 59 queue <SEG> team;
 60
 61 inline bool para(LINE l1,LINE l2) { return equal(l1.a * l2.b,l1.b * l2.a); }
 62
 63 inline double qua(double a) { return a * a; }
 64
 65 inline double dis(NODE a,NODE b) { return sqrt(qua(a.x - b.x)+qua(a.y - b.y)); }
 66
 67 inline NODE cp(LINE l1,LINE l2)
 68 {
 69     double a1 = l1.a,b1 = l1.b,c1 = l1.c;
 70     double a2 = l2.a,b2 = l2.b,c2 = l2.c;
 71     double ry = (c2*a1-c1*a2)/(b1*a2-b2*a1),rx = (c1*b2-c2*b1)/(b1*a2-b2*a1);
 72     return (NODE) {rx,ry};
 73 }
 74
 75 inline void cross(SEG s,int now)
 76 {
 77     LINE l = s.extend(),l1; SEG t; NODE p; NODE tt[maxm];
 78     int cnt = 0;
 79     for (int i = 1;i <= have[now];++i)
 80     {
 81         t = (SEG) {pol[now][i],pol[now][i-1]};
 82         l1 = t.extend();
 83         if (para(l,l1))
 84         {
 85             if (l == l1)
 86             {
 87                 if (s.on(t.a)) tt[++cnt] = t.a;
 88                 if (s.on(t.b)) tt[++cnt] = t.b;
 89             }
 90             continue;
 91         }
 92         p = cp(l,l1);
 93         if (t.on(p) && s.on(p))
 94             tt[++cnt] = p;
 95     }
 96     sort(tt+1,tt+cnt+1);
 97     for (int i = 1;i <= cnt;++i) bac[++tot] = tt[i];
 98 }
 99
100 inline NODE find(NODE p)
101 {
102     NODE ret,q; LINE l1,l2; SEG s; double best = 1e9,len;
103     for (int i = 1;i <= c;++i)
104         for (int j = 1;j <= have[i];++j)
105         {
106             s = (SEG) {pol[i][j],pol[i][j-1]};
107             l1 = s.extend();
108             l2 = l1.vert(p);
109             q = cp(l1,l2);
110             if (s.on(q))
111             {
112                 len = dis(p,q);
113                 if (best > len) ret = q,best = len;
114             }
115             else
116             {
117                 if (dis(p,s.a) < dis(p,s.b)) q = s.a;
118                 else q = s.b;
119                 len = dis(p,q);
120                 if (best > len) ret = q,best = len;
121             }
122         }
123     return ret;
124 }
125
126 inline bool in(NODE p)
127 {
128     NODE q = p.ra(); SEG s = (SEG) {p,q},t; LINE l = s.extend(),l1; int cnt;
129     for (int i = 1;i <= c;++i)
130     {
131         cnt = 0;
132         for (int j = 1;j <= have[i];++j)
133         {
134             t = (SEG) {pol[i][j],pol[i][j-1]};
135             if ((t.extend()).on(p)&&t.on(p)) return false;
136             l1 = t.extend();
137             if (para(l,l1)) continue;
138             q = cp(l,l1);
139             if (dd(q.x,p.x)&&t.on(q)) ++cnt;
140         }
141         if (cnt & 1) return true;
142     }
143     return false;
144 }
145
146 inline void init()
147 {
148     for (int i = 1;i < n;++i)
149     {
150         tot = 0;
151         if (!(temp[i].a < temp[i].b)) swap(temp[i].a,temp[i].b);
152         for (int j = 1;j <= c;++j)
153             cross(temp[i],j);
154         if (!in(temp[i].a)) bac[++tot] = temp[i].a;
155         if (!in(temp[i].b)) bac[++tot] = temp[i].b;
156         sort(bac+1,bac+tot+1);
157         for (int j = 1;j < tot;j++)
158             if (!in((SEG){bac[j],bac[j+1]}.MID()))
159                 team.push((SEG){bac[j],bac[j+1]});
160      }
161 }
162
163 inline void work()
164 {
165     SEG now; NODE mid,p1,p2,l,r; double ret;
166     while (!team.empty())
167     {
168         now = team.front(); team.pop();
169         if (!now.exist()) continue;
170         p1 = find(now.a); p2 = find(now.b);
171         l = now.a,r = now.b;
172         while (!(l == r))
173         {
174             mid = ((SEG){l,r}).MID();
175             if (dis(p1,mid) > dis(p2,mid)) r = mid;
176             else l = mid;
177         }
178         ret = dis(r,p1);
179         ans = max(max(dis(now.a,p1),dis(now.b,p2)),ans);
180         if (ret-esp < ans) continue;
181         mid = now.MID();
182         team.push((SEG){now.a,mid}),team.push((SEG){mid,now.b});
183     }
184 }
185
186 int main()
187 {
188     srand(233);
189     ans = 0;
190     scanf("%d %d ",&c,&n);
191     NODE p1,p2; p1.read();
192     for (int i = 2;i <= n;++i)
193     {
194         p2.read(); temp[i-1] = (SEG) {p1,p2};
195         p1 = p2;
196     }
197     for (int i = 1;i <= c;++i)
198     {
199         scanf("%d ",have+i);
200         for (int j = 1;j <= have[i];++j) pol[i][j].read();
201         pol[i][0] = pol[i][have[i]];
202     }
203     init();
204     work();
205     printf("%.2lf\n",ans);
206     fclose(stdin); fclose(stdout);
207     return 0;
208 }

View Code

转载于:https://www.cnblogs.com/mmlz/p/4211827.html

BZOJ 1020 安全的航线flight相关推荐

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

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

  2. 嵌入式系统linux下bond,CentOS双网卡绑定bond0

    a)拷⻉并配置vim /etc/sysconfig/network-scripts/ifcfg-bond0配置⽂件(会自动创建文件) DEVICE=bond0 TYPE=Ethernet ONBOOT ...

  3. 8月清北学堂培训 Day4

    今天上午是赵和旭老师的讲授~ 概率与期望 dp 概率 某个事件 A 发生的可能性的大小,称之为事件 A 的概率,记作 P ( A ) . 假设某事的所有可能结果有 n 种,每种结果都是等概率,事件 A ...

  4. 2019.3.summary

    emmmm,把以前写的2b总结丢上来吧,不过应该也不会有人看QAQ (注:因为用txt写的,有一些公式打的很随意,放到markdown上公式自动排版,有可能会显示出错误!可在下方留言) 2019.2. ...

  5. [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  6. 【BZOJ】1969: [Ahoi2005]LANE 航线规划

    题目链接: 传送~~ 题解:  老夫实在是码不动了-- 正着搞显然不好做,尝试倒着乱搞.先给被删除的边标记一个时间戳,先删除的时间戳大,同时维护询问时间戳,询问早的时间戳大.没被删除过的边时间戳都是0 ...

  7. 【航线运输驾驶员理论考试】气象学

    1.TAF is the weather forcast information applied to an area within ( ) from the center of an airport ...

  8. 【航线运输驾驶员理论考试】人的行为能力

    1.The main function of hemoglobin is to(血红蛋白的主要功能是) A. hemostasis(止血作用) B. carry oxygen around to bo ...

  9. 【航线运输驾驶员理论考试】领航

    1.(Refer to figures ATP6-1) What is the runway distance remaining at "A" for a daytime tak ...

最新文章

  1. 026-请问你怎么测试网络协议
  2. js作用域链以及全局变量和局部变量
  3. python分块处理功能_python 对列表分块
  4. 深入探究ASP.NET Core Startup的初始化
  5. java socket 阻塞模式_(四) 如何将socket设置为非阻塞模式
  6. how hurt my eggs are, if two, please deep two.
  7. 线性逻辑回归logistic regression
  8. 手动搭建vue+node单页面(一)
  9. 有了net send,谁还用IM?
  10. excel转word后表格超出页面_妙招!Word和Execl“联姻”实现数据高效处理!
  11. 生成.pkl文件,读取.pkl文件的内容
  12. 张宇八套卷(二)复盘
  13. Android ------ 开源的Modnet算法实现抠图和更换背景
  14. MSC-51单片机原理与实践——第四章习题及答案解析
  15. QT 基于Libvlc的视频播放器
  16. android调用摄像头录像的代码(录像并生成mp4文件)
  17. 【R语言数据科学】:(三)数据基础处理(mutate、filter、select等)
  18. 读书笔记2014第6本:《The Hunger Games》
  19. MySql 练习- 留存率计算
  20. 未来大数据发展和就业前景:大数据人才缺口到底有多大?

热门文章

  1. ICML2021 | ALIGN:大力出奇迹,谷歌用18亿的图像-文本对训练了一个这样的模型
  2. 太强了!机器视觉相机解决硬币制造难题!
  3. 使用 YOLOv5 训练自动驾驶目标检测网络
  4. CVPR 2020 论文大盘点-人体姿态估计与动作捕捉篇
  5. 详细解读Python 递归函数!
  6. 700 页的机器学习总结火了!
  7. 内推|商汤科技深度学习方向实习生
  8. 通用汽车研发中心最新提出:3D车道线检测新方法
  9. 物体检测的过去、现在和未来
  10. 为什么要 conda 作用_武汉精神堡垒有什么作用 为什么要做?