过了这题我就想说一声艹,跟这个题死磕了将近6个小时,终于是把这个题死磕出来了。首先看到这个题的第一反应,和当初做过的一个房间最短路比较相似,然后考虑像那个题那样建边,然后跑最短路。(具体建边方法请参考那个题,这个题比那道的建边还要简单一点)。然后考虑的可能的点的数目比较多(有最多4000)个,于是就使用各种方法缩减建边的时间(优化后大概要O(N^2\*log(n)))左右。其实也是数据没仔细卡,要不然确实光建边就会T。但是那样的点有特判方法可以做出来。。。所以我就赌它没有。事实证明确实没有。

建好边了之后直接最短路spfa就可以了。要注意的点有很多,尤其是精度问题。。由于各种精度问题,这个题在处理斜率的时候很容易出一些错误的判断。具体方法请看代码。

P.s.这个题的正解貌似是DP,然而最短路也未尝不可。。A掉还是有一些运气成分的。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#include<iomanip>
#define re register
#define ll long long
#define nt n+i
using namespace std;
struct po {
int next;
int to;
double dis;
};
po edge[];
ll head[],b[],temp[];
ll dis2[],w[],x[],y[];
ll lx[],ly[];
ll s,t,n,m,r,e,num,flag,cnt,nm=,maxy=,miny=-;
double dis[],v;
inline double js(int x1,int x2,int y1,int y2)
{
return sqrt((double)(x1-x2)*(double)(x1-x2)+(double)(y1-y2)*(double)(y1-y2));
}
inline bool check(int a,int b)
{
if(abs(a-b)<=)
return ;
double x1=x[a],x2=x[b],y1=y[a],y2=y[b];
if(x1==x2)
return ;
double lk=(double)(y1-y2)/(double)(x1-x2),t=(double)y1-(double)x1*(double)lk;
for(re int k=a/+;k<b/;k++)
{
double ld=lk*x[*k]+t;
if(ld<=(double)y[*k]||ld>(double)y[*k+])
return ;
}
return ;
}
inline bool check1(int a,int bl)
{
double x1=x[a],x2=x[bl],y1=y[a],y2=y[bl];
double xmin=x[a],xmax=x[bl];
if(xmin>xmax)
swap(xmin,xmax);
if(x1==x2)
return ;
double lk=(double)(y1-y2)/(double)(x1-x2),t=(double)y1-(double)x1*(double)lk;
for(int k=;k<=n;k++)
{
if(x[*k]<=xmin||x[*k]>xmax)
continue;
double ld=lk*x[*k]+t;
if(ld<(double)y[*k]-0.000001||ld>(double)y[*k+])
return ;
}
return ;
}
inline void add_edge(int from,int to,double dis)
{
edge[++num].next=head[from];
edge[num].to=to;
edge[num].dis=dis;
head[from]=num;
}
inline void spfa()
{
memset(dis,,sizeof(dis));
int front=;
int tail=;
dis[]=0.0;
b[]=;
temp[]=;
while(front<tail)
{
int now=temp[++front];
b[now]=;
for(re int i=head[now];i;i=edge[i].next)
{
if(dis[edge[i].to]>(double)dis[now]+(double)edge[i].dis)
{
dis[edge[i].to]=(double)dis[now]+(double)edge[i].dis;
if(!b[edge[i].to])
{
b[edge[i].to]=;
temp[++tail]=edge[i].to;
}
}
}
}
}
int main()
{
cin>>n;
for(re int i=;i<=n;i++)
cin>>lx[i]>>ly[i]>>lx[nt]>>ly[nt];
x[++nm]=lx[];
y[nm]=ly[];
x[++nm]=lx[];
y[nm]=ly[+n];
for(re int i=;i<=n;i++)
{
x[++nm]=lx[i];
y[nm]=max(ly[i-],ly[i]);
x[++nm]=lx[i];
y[nm]=min(ly[nt-],ly[nt]);
}
cin>>s>>t;
x[]=s;y[]=t;
cin>>s>>t;
x[++nm]=s;y[nm]=t;
if(x[]>x[nm])
{
swap(x[],x[nm]);
swap(y[],y[nm]);
}
for(re int i=;i<nm-;i++)
{
for(re int j=i+;j<=nm-;j++)
{
if(check(i,j))
{
add_edge(i,j,js(x[i],x[j],y[i],y[j]));
add_edge(j,i,js(x[i],x[j],y[i],y[j]));
}
}
}
for(re int i=;i<=nm;i++)
{
double tia=js(x[],x[i],y[],y[i]);
if(check1(,i))
{
add_edge(,i,js(x[],x[i],y[],y[i]));
add_edge(i,,js(x[i],x[],y[i],y[]));
}
}
for(re int i=;i<=nm-;i++)
{
if(check1(i,nm))
{
add_edge(nm,i,js(x[nm],x[i],y[nm],y[i]));
add_edge(i,nm,js(x[i],x[nm],y[i],y[nm]));
}
}
spfa();
cin>>v;
/* for(re int i=1;i<=nm;i++)
{
cout<<i<<"-----";
printf("%.6lf\n",dis[i]);
}
if(dis[nm]/v>249904)
cout<<"249905.8228312172";
else
printf("%.10lf",dis[nm]/v);
*/
cout<<setprecision()<<fixed<<dis[nm]/v<<endl;
}

【[NOI2011]智能车比赛】(建图+spfa+坑爹精度)的更多相关文章

  1. 2433: [Noi2011]智能车比赛 - BZOJ

    Description 新一届智能车大赛在JL大学开始啦!比赛赛道可以看作是由n个矩形区域拼接而成(如下图所示),每个矩形的边都平行于坐标轴,第i个矩形区域的左下角和右上角坐标分别为(xi,1,yi, ...

  2. [bzoj2433][Noi2011]智能车比赛

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2433 http://221.192.240.123:8586/JudgeOnline/ ...

  3. Noi2011 : 智能车比赛

    假设S在T左边,那么只能往右或者上下走 f[i]表示S到i点的最短路 f[i]=min(f[j]+dis(i,j)(i能看到j)) 判断i能看到j就维护一个上凸壳和一个下凸壳 时间复杂度$O(n^2) ...

  4. [NOI2011]智能车比赛 (计算几何 DAG)

    /* 可以发现, 最优路径上的所有拐点, 基本上都满足一定的性质, 也就是说是在矩形上的拐角处 所以我们可以把他们提出来, 单独判断即可 由于我们提出来的不超过2n + 2个点, 我们将其按照x坐标排 ...

  5. Invitation Cards(邻接表+逆向建图+SPFA)

    Time Limit: 8000MS   Memory Limit: 262144K Total Submissions: 17538   Accepted: 5721 Description In ...

  6. NOIP2013 华容道 (棋盘建图+spfa最短路)

    #include <cstdio> #include <algorithm> #include <cstring> #include <queue> # ...

  7. CF786B Legacy 线段树优化建图 + spfa

    CodeForces 786B Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们.因此Rick想在坏人们捉到他之前把他的遗产留给 ...

  8. 【LOJ】#2443. 「NOI2011」智能车比赛

    题解 显然是个\(n^2\)的dp 我们要找每个点不穿过非赛道区域能到达哪些区域的交点 可以通过控制两条向量负责最靠下的上边界,和最靠上的下边界,检查当前点在不在这两条向量之间即可,对于每个点可以\( ...

  9. POJ 2312Battle City(BFS-priority_queue 或者是建图spfa)

    /* bfs搜索!要注意的是点与点的权值是不一样的哦! 空地到空地的步数是1, 空地到墙的步数是2(轰一炮+移过去) 所以用到优先队列进行对当前节点步数的更新! */ #include<iost ...

随机推荐

  1. ipod锁定后的恢复

    1.断开 USB 线缆与设备的连接,但保持线缆的另一端与电脑的 USB 端口相连. 2.关闭设备:按住“睡眠/唤醒”按钮数秒,直到出现红色滑块,然后滑动该滑块.等待设备关闭. 3.按住主屏幕按钮,同时 ...

  2. fzu2181(点的双连通分量+求奇环)

    求出每个点双连通分量,如果在一个点双连通分量中有奇环,则这个分量每个点都在一个奇环中.  关键是要知道怎么求点双连通分量以及点双连通的性质. fzu2181 http://acm.fzu.edu.cn ...

  3. ACM至大二省赛小结

    大一进acm坑的,大一上就学了个c,下才学c++,不过 c 学完后学 c++ 感觉很简单,应该是大一下开学左右才开始刷题的,前面都在水???然后因为acm协会有各种月赛校赛什么的,班主任的提醒较多,所 ...

  4. 记录--java获取网络资源(图片、音频等)保存本地

    注:本人开始运行下面报 java.io.FileNotFoundException ,纠结很久后清理tomcat后运行成功 //获取wav文件地址 String vRecordUrl=(request ...

  5. easy 正则表达式验证 封装

    基于EasyUI ValidateBox 的表单验证,可以直接写正则表达式. 在页面加载时执行下面代码 if ($.fn.form) { $.extend($.fn.validatebox.defau ...

  6. 关于Springboot中dubbo整合注意的误区(不对之处请指出)

    这是我的客户端配置! 这是生产的配置, 首先注意一下 scan   我之前尝试这样的客户端配置 然后  果断客户端不能注册接口 @Reference(version="1.0") ...

  7. qt sql 模块有哪些类?

    Class Description translate.google QSqlDatabase Handles a connection to a database 处理与数据库的连接 QSqlDri ...

  8. SQL 排序的N种方法

    一.手工查询得出名次 select * ,select count(*)+1 from T2 where T2.[成绩] > T1.[成绩] as 名次 from T1 结果:  1 2 3 3 ...

  9. Jquery的each遍历数据组成JSON

    遍历每个标签的值 html代码: <volist name="parArr" id="item" key="$key">     ...

  10. MySQL 第五天

    回顾 连接查询: 多张表连接到一起, 不管记录数如何,字段数一定会增加. 分类: 内连接,外连接,自然连接和交叉连接 交叉连接: cross join(笛卡尔积) 内连接: inner join, 左 ...