[NOI2011]智能车比赛(计算几何+动态规划)
2015-03-16 00:49
337 查看
【题解】
路径只在矩形顶点处拐弯,因此可以建4*n+2个点,求最短路
那么只需判断哪些点对能够直接连边
直接枚举点对并建图,复杂度为O(n^3),优化:枚举点u和其他所有点能否连边时,可以利用一个天然的单调性:这些点横坐标是从左到右的
从左到右枚举点u,用u来更新最短路,对于每个u,维护从它出发的上下视线(两个向量),另一个点v的枚举依然是从左到右推进
这样,要判断u,v能否以线段相连接,只需判断v是否在当前的视野内(向量叉积)即可
最短路不专门求,而是在维护视野的过程中求得 O(n^2)
【代码】
路径只在矩形顶点处拐弯,因此可以建4*n+2个点,求最短路
那么只需判断哪些点对能够直接连边
直接枚举点对并建图,复杂度为O(n^3),优化:枚举点u和其他所有点能否连边时,可以利用一个天然的单调性:这些点横坐标是从左到右的
从左到右枚举点u,用u来更新最短路,对于每个u,维护从它出发的上下视线(两个向量),另一个点v的枚举依然是从左到右推进
这样,要判断u,v能否以线段相连接,只需判断v是否在当前的视野内(向量叉积)即可
最短路不专门求,而是在维护视野的过程中求得 O(n^2)
【代码】
#include<stdio.h> #include<stdlib.h> #include<math.h> #define INF 1000000000 double d[8010]={0}; int x_1[2010]={0},y_1[2010]={0},x_2[2010]={0},y_2[2010]={0},x[8010]={0},y[8010]={0},pla[8010]={0}; int tot=0; void jh(int* a,int* b) { int t=*a; *a=*b; *b=t; } double dis(int x1,int y1,int x2,int y2) { return sqrt( (double)((x1-x2)*(x1-x2))+(double)((y1-y2)*(y1-y2)) ); } int cross(int x1,int y1,int x2,int y2) { return x1*y2-x2*y1; } void update(int s) { int i=s,xu=x[s],yu=y[s]+1,xd=x[s],yd=y[s]-1;//初始视线保证不能往x轴负方向走 while(i>1&&x[i]==x[i-1]) i--; for(;i<=tot;i++) { if(cross(xd-x[s],yd-y[s],x[i]-x[s],y[i]-y[s])>=0&&cross(xu-x[s],yu-y[s],x[i]-x[s],y[i]-y[s])<=0)//在视野内:更新最距离 if(d[i]>d[s]+dis(x[s],y[s],x[i],y[i])) d[i]=d[s]+dis(x[s],y[s],x[i],y[i]); if(pla[i]!=0&&(x[s]!=x[i]||y[s]!=y[i]))//维护上下视线(不能只在:i在视野内 时才维护; i与s为同一个点:不维护) { if(pla[i]==2&&cross(xu-x[s],yu-y[s],x[i]-x[s],y[i]-y[s])<=0)//上方点在上边界下方 { xu=x[i]; yu=y[i]; } if(pla[i]==1&&cross(xd-x[s],yd-y[s],x[i]-x[s],y[i]-y[s])>=0)//下方点在下边界上方 { xd=x[i]; yd=y[i]; } } if(cross(xd-x[s],yd-y[s],xu-x[s],yu-y[s])<0) return; } } int main() { double v; int n,i,xs,ys,xt,yt,tou,wei,t; scanf("%d",&n); for(i=1;i<=n;i++) scanf("%d%d%d%d",&x_1[i],&y_1[i],&x_2[i],&y_2[i]); scanf("%d%d%d%d",&xs,&ys,&xt,&yt); scanf("%lf",&v); if(xs>xt) { jh(&xs,&xt); jh(&ys,&yt); } for(tou=1;tou<=n;tou++)//找到s所在的矩形 if(xs<=x_2[tou]&&y_1[tou]<=ys&&ys<=y_2[tou]) break; for(wei=n;wei>=1;wei--)//找到t所在的矩形 if(x_1[wei]<=xt&&y_1[wei]<=yt&&yt<=y_2[wei]) break; x[0]=xs; y[0]=ys; for(i=tou;i<=wei;i++) { if(x_1[i]==xt&&y_1[i]<=yt&&yt<=y_2[i])//t在矩形i左边界(线段)上,使它最靠左编号 { x[++tot]=xt; y[tot]=yt; t=tot; } x[++tot]=x_1[i]; y[tot]=y_1[i]; pla[tot]=1;//1 (左)下 x[++tot]=x_1[i]; y[tot]=y_2[i]; pla[tot]=2;//2 (左)上 if(x_1[i]<xt&&xt<=x_2[i]&&y_1[i]<=yt&&yt<=y_2[i])//t在矩形i内部 { x[++tot]=xt; y[tot]=yt; t=tot; } x[++tot]=x_2[i]; y[tot]=y_1[i]; pla[tot]=1;//1 (右)下 x[++tot]=x_2[i]; y[tot]=y_2[i]; pla[tot]=2;//2 (右)上 } for(i=1;i<=tot;i++) d[i]=INF; for(i=0;i<=tot;i++) update(i); printf("%.10lf",d[t]/v); return 0; }
相关文章推荐
- [BZOJ 2433][NOI 2011]智能车比赛(计算几何+动态规划)
- bzoj 2433 [Noi2011]智能车比赛 [计算几何+spfa]
- Noi2011 : 智能车比赛
- [NOI2011 智能车比赛]
- 【bzoj 2433】【NOI 2011】 智能车比赛 题意&题解&代码(C++)
- 2433: [Noi2011]智能车比赛 - BZOJ
- 【bzoj 2433】【NOI 2011 D1T2】 智能车比赛 想法乱搞+暴力
- noi 2011 智能车比赛
- [bzoj2433][Noi2011]智能车比赛
- 【DP】[NOI2011]智能车比赛
- 【LOJ】#2443. 「NOI2011」智能车比赛
- ★【视野动态规划】【NOI2011】智能车比赛
- NOI2011 智能车比赛
- 【BZOJ 2433】[Noi2011]智能车比赛
- BZOJ2434 [Noi2011]阿狸的打字机 【AC自动机 + fail树 + 树状数组】
- 独立、原创、总结、分享、行动——由海滨学生参观实验室及“飞思卡尔”杯智能车比赛想到的
- 2436: [Noi2011]Noi嘉年华 - BZOJ
- BZOJ 2434: [Noi2011]阿狸的打字机【AC自动机,fail树.dfs序,树状数组
- BZOJ 2434: [Noi2011]阿狸的打字机( AC自动机 + DFS序 + 树状数组 )
- 洛谷 P1808 单词分类_NOI导刊2011提高(01)