计算几何/二分/迭代/搜索+剪枝


  写三个tag可能是因为从哪个方向来理解都可以吧……

  我完全不会计算几何所以抄了ydc的代码

  题解:http://ydcydcy1.blog.163.com/blog/static/21608904020131492229367/

  那篇莫涛的论文:http://pan.baidu.com/s/1bn6IxJp

大概流程如下:

  1.初始化孤地点可能位于的线段集合为整条航线。

  2.对于长$L$的某条线段,左端点与陆地的最近点为$P_1$,右端点与陆地的最近点为$P_2$,那么该线段上的孤地距离将受$P_1$与$P_2$影响。具体来说,利用二分求出改线段上的点$P$使得$$ Minimize \ y = max\{Dis\{P,P_1\},Dis\{P,P_2\}\}$$若$y$小于已有的最优答案,那么可以删除该线段。

  3.取所有线段的中点更新答案。

  4.将所有线段从重点分成左右两条线段。

  5.不断进行2,3,4直到线段的集合为空。

  整个过程中最复杂的计算集合操作是第3步中求点与线段的距离,并且不会出现因精度导致的判断问题,而运行速度也不错,极限数举只需0.05秒,是一个相当优秀的算法。

(才怪啊!那判断点是否在陆地上不是也得写射线法和点在线段上?判断是否在多边形内部……)

 /**************************************************************
Problem: 1020
User: Tunix
Language: C++
Result: Accepted
Time:92 ms
Memory:32544 kb
****************************************************************/ //BZOJ 1020
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
#define pb push_back
using namespace std;
inline int getint(){
int v=,sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
return v*sign;
}
const int N=,M=,MAXQ=1e6,INF=~0u>>;
const double eps=1e-;
typedef long long LL;
typedef double db;
/******************tamplate*********************/
int dcmp(db p){if(fabs(p)<eps) return ;else return p>eps?:-;}
int n,m;
db ans;
struct Point{
db x,y;
Point(){}
Point(db x,db y):x(x),y(y){}
void Read(){scanf("%lf %lf",&x,&y);}
}temp[N];
Point operator + (const Point &a,const Point &b){return Point(a.x+b.x,a.y+b.y);}
Point operator - (const Point &a,const Point &b){return Point(a.x-b.x,a.y-b.y);}
Point operator * (const Point &a,db p){return Point(a.x*p,a.y*p);}
Point operator / (const Point &a,db p){return Point(a.x/p,a.y/p);}
bool operator == (const Point &a,const Point &b){return !dcmp(a.x-b.x)&&!dcmp(a.y-b.y);}
typedef Point Vector;
double Dot(const Vector &a,const Vector &b){return a.x*b.x+a.y*b.y;}
double Len(const Vector &a){return sqrt(Dot(a,a));}
double Cross(const Vector &a,const Vector &b){return a.x*b.y-a.y*b.x;}
Vector Normal(const Vector &a){return Vector(-a.y,a.x);}
bool On(const Point &a,const Point &b,const Point &c){
return !dcmp(Cross(b-a,c-a))&&
dcmp((a.x-b.x)*(a.x-c.x))<=&&dcmp((a.y-b.y)*(a.y-c.y))<=;
}
bool inter(const Point &a,const Point &b,const Point &c,const Point &d){
return dcmp(Cross(c-a,b-a)*Cross(d-a,b-a))<= && dcmp(Cross(a-c,d-c)*Cross(b-c,d-c))<=;
}
Point getinter(const Point &a,const Vector &b,const Point &c,const Vector &d){
Vector u=a-c;
double t=Cross(d,u)/Cross(b,d);
return a+b*t;
}
struct Seg{
Point a,b;
Seg(){}
Seg(const Point &a,const Point &b):a(a),b(b){}
}queue[MAXQ];
struct Polygon{
Point p[M];
int tot;
bool In(Point &point){
int total=;
F(i,,tot)
if (On(point,p[i],p[i%tot+]))
return true;
Point Ray=Point(-,point.y+0.1);
point.y+=0.1;
F(i,,tot)
total=total+inter(Ray,point,p[i],p[i%tot+]);
point.y-=0.1;
return total&;
}
}island[N];
struct near{
Point P;
double dis;
near(){}
near(const Point &a,double b):P(a),dis(b){}
};
near DISPS(const Point &a,const Point &b,const Point &c){
if (b==c) return near(b,Len(b-a));
Vector v1=c-b,v2=a-b,v3=a-c;
if (dcmp(Dot(v1,v2))<=) return near(b,Len(v2));
if (dcmp(Dot(v1,v3))>=) return near(c,Len(v3));
Vector v=Normal(b-c);
Point ans=getinter(a,v,b,v1);
return near(ans,Len(a-ans));
}
bool check(Point &P){
F(i,,n)
if (island[i].In(P))
return true;
return false;
}
near Find(Point &P){
if (check(P)) return near(P,);
near ans1;
ans1.dis=<<;
F(i,,n)
F(j,,island[i].tot){
near get=DISPS(P,island[i].p[j],island[i].p[j%island[i].tot+]);
if (dcmp(ans1.dis-get.dis)>=) ans1=get;
}
ans=max(ans,ans1.dis);
return ans1;
}
void read(){
n=getint(); m=getint();
F(i,,m) temp[i].Read();
F(i,,n){
island[i].tot=getint();
F(j,,island[i].tot)
island[i].p[j].Read();
}
}
void search(){
int front=,rear=;
F(i,,m-)
queue[++rear]=Seg(temp[i],temp[i+]),Find(temp[i]);
Find(temp[m]);
Seg head;
while(front!=rear){
head=queue[front=front%MAXQ+];
Point p1=Find(head.a).P,p2=Find(head.b).P,
l=head.a,r=head.b,mid=(l+r)/;
while(Len(r-l)>1e-){
Point mid=(r+l)/;
if (Len(mid-p1)<Len(mid-p2)) l=mid;
else r=mid;
}
double nowans=max(Len(l-p1),Len(l-p2));
Find(l);
if (ans+0.005<nowans)
queue[rear=rear%MAXQ+]=Seg(head.a,mid),
queue[rear=rear%MAXQ+]=Seg(mid,head.b);
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("1020.in","r",stdin);
freopen("1020.out","w",stdout);
#endif
read();
search();
printf("%.2lf\n",ans);
return ;
}

1020: [SHOI2008]安全的航线flight

Time Limit: 1 Sec  Memory Limit: 162 MB
Submit: 786  Solved: 254
[Submit][Status][Discuss]

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

HINT

Source

[Submit][Status][Discuss]

【BZOJ】【1020】【SHOI2008】安全的航线flight的更多相关文章

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

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

  2. 1020: [SHOI2008]安全的航线flight - BZOJ

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

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

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

  4. BZOJ 1020 安全的航线flight

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

  5. bzoj 1023: [SHOI2008]cactus仙人掌图 tarjan缩环&&环上单调队列

    1023: [SHOI2008]cactus仙人掌图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1141  Solved: 435[Submit][ ...

  6. bzoj 1022: [SHOI2008]小约翰的游戏John anti_nim游戏

    1022: [SHOI2008]小约翰的游戏John Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1189  Solved: 734[Submit][ ...

  7. [BZOJ 1018] [SHOI2008] 堵塞的交通traffic 【线段树维护联通性】

    题目链接:BZOJ - 1018 题目分析 这道题就说明了刷题少,比赛就容易跪..SDOI Round1 Day2 T3 就是与这道题类似的..然而我并没有做过这道题.. 这道题是线段树维护联通性的经 ...

  8. 数据结构(线段树):BZOJ 1018: [SHOI2008]堵塞的交通traffic

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 2638  Solved: 864 Descri ...

  9. BZOJ 1021 [SHOI2008]Debt 循环的债务

    1021: [SHOI2008]Debt 循环的债务 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 694  Solved: 356[Submit][S ...

随机推荐

  1. 别不拿里程碑当石头---------IT项目管理之项目计划(转)

    如果说做项目不需要计划,恐怕没人会认同.是否每个项目计划都起到了作用呢?却不尽然.知道要做计划,但不知道为什么做计划,如何做计划的还是大有人在.所以很多计划沦为依样画葫芦,成了摆设. IT项目计划的用 ...

  2. 《第一行代码--Android》阅读笔记之界面设计

    1.单位dp.dip.sp.pt.px.in.mm 这里引用StackOverFlow上的一个解答: px is one pixel. sp is scale-independent pixels. ...

  3. Linux基础知识-文件管理

    Linux目录与路径 cd:切换目录 例如:cd ~willhua,则回到用户willhua的主文件夹  cd ~或者cd,则表示回到自己的的主文件夹  cd -,则表示回到上个目录 pwd:显示目前 ...

  4. centos6.7下编译安装lnmp

    很多步骤不说明了,请参照本人的centos6.7下编译安装lamp,这次的架构是nginx+php-fpm一台服务器,mysql一台服务器 (1)首先编译安装nginx: 操作命令: yum -y g ...

  5. php中intval()函数

    格式:int intval(mixed $var [, int $base]); 1.intval()的返回值是整型,1或者0.可作用于数组或者对象(对象报错信息:Notice: Object of ...

  6. SQL Server中查询结果拼接遇到的小问题

    前天的项目,刚接手,对于模块还不是很熟悉,其中有一个模块,涉及到4个表,其中主要的表就有两个,只要把这个弄清楚了就一切回归于“太平”了. 模块要求:把两个表的内容查询出来,结果连接在一起.大师说完,感 ...

  7. Ksoap2 获取webservice返回值的getResponse() 出现的问题

    今天写了一个判断记录重复的webservcie 返回布尔类型 // 判断序列号在数据库是否重复 public static boolean isSerialNumExist(String serial ...

  8. python实现 _ 图书馆书籍到期之前_自动邮件提醒

    一共两个脚本: 第一个是[借书完毕以及借书信息有变更(续借等)]的时候需要执行的脚本:实现模拟登陆,同时最新的借书信息的下载到本地文本:之所以没有这样做,是因为如果每次爬取一遍的话,需要每次输入一遍验 ...

  9. Oracle Database Concepts:介绍模式对象(Introduction to Schema Objects)

    数据库模式(schema)是数据结构的逻辑容器,被称作模式对象(schema objects) 每一个数据库用户拥有一个和用户名相同的模式,例如hr用户拥有hr模式. 在一个产品数据库中,模式的拥有者 ...

  10. .NET开源工作流RoadFlow-流程设计-流程步骤设置-基本设置

    流程属性设置完成后点击确定之后,即可进行流程步骤设置了. 点击工具栏上的步骤按钮,即可添加一个新步骤. 在新步骤图形上双击即可弹出该步骤相应属性设置框. 步骤ID:系统自动为该步骤生成的唯一ID. 步 ...