POJ 1066 Treasure Hunt 判断两线段是否相交
2013-08-29 10:34
369 查看
本题关键:如何找到最少的路径。
刚刚做的一题计算几何时建图的,做到这道题,第一个想法就是建图,找最短路, 后来细想操作太多太繁琐,不好做, 所以放弃了,觉得应该有简单的做法。
思考很关键:从外围四个墙的某一个门进来,走到宝藏,最小走几个门,实际就是进门点和宝藏的连线goalLine穿过几个点。
证明不好证,但如果说明大体的思想其实挺简单的:思想有点像两点之间直线最短。不要去管纵横交错的小线段,只管一开始原始输入的线段,因为在正方形范围内,这些线段可以想象为无限长,进门的点和宝藏点中间横跨着k条直线(墙 ),你就无法绕过它们,只能穿过它们 ,你往左往右走都只会徒增加你要穿过的墙,就这最基本的k道墙你总是要穿过。
但这样做还是很麻烦,枚举每个中点毕竟还是很繁琐的,再仔细想想,能不能枚举每个边缘的端点呢,画了很多种情况,觉得应该还是可以的,敲了一遍, 结果 AC,哈哈;
思考真的狠关键,千万别偷懒,如果想偷懒,还不如不搞ACM,假如你做一道题,没有思路之前就不必敲键盘了,这会是无用功,思考真的很重要,毕竟算法和模板大家学的都是一样的。
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
View Code
刚刚做的一题计算几何时建图的,做到这道题,第一个想法就是建图,找最短路, 后来细想操作太多太繁琐,不好做, 所以放弃了,觉得应该有简单的做法。
思考很关键:从外围四个墙的某一个门进来,走到宝藏,最小走几个门,实际就是进门点和宝藏的连线goalLine穿过几个点。
证明不好证,但如果说明大体的思想其实挺简单的:思想有点像两点之间直线最短。不要去管纵横交错的小线段,只管一开始原始输入的线段,因为在正方形范围内,这些线段可以想象为无限长,进门的点和宝藏点中间横跨着k条直线(墙 ),你就无法绕过它们,只能穿过它们 ,你往左往右走都只会徒增加你要穿过的墙,就这最基本的k道墙你总是要穿过。
但这样做还是很麻烦,枚举每个中点毕竟还是很繁琐的,再仔细想想,能不能枚举每个边缘的端点呢,画了很多种情况,觉得应该还是可以的,敲了一遍, 结果 AC,哈哈;
思考真的狠关键,千万别偷懒,如果想偷懒,还不如不搞ACM,假如你做一道题,没有思路之前就不必敲键盘了,这会是无用功,思考真的很重要,毕竟算法和模板大家学的都是一样的。
![](http://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](http://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
View Code
#include<stdio.h> #include<string.h> #include<math.h> #include<algorithm> using namespace std; #define eps 10e-8 struct point { double x, y; point(){} point(double xx, double yy) : x(xx), y(yy){} }; struct seg { point a, b; seg(){} seg(point aa, point bb) : a(aa), b(bb){} }s[36]; int n; point p[70],dest; int ans, cnt1, cnt2; double cross(point o, point p1, point p2)//叉积 { return (p1.x - o.x)*(p2.y - o.y) - (p1.y - o.y)*(p2.x -o.x); } bool seg_cross(seg s1, point p1, point p2)//判断两线段是否相交(b不考虑共线,本题不可能共线) { if(cross(s1.a, s1.b, p1)*cross(s1.a, s1.b, p2)< -eps &&cross(p1, p2, s1.a)*cross(p1, p2, s1.b) < -eps) return 1; return 0; } int main() { int i, j; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) scanf("%lf%lf%lf%lf",&s[i].a.x, &s[i].a.y, &s[i].b.x, &s[i].b.y); s[n+1] = seg(point(0, 0), point(0, 100)); s[n+2] = seg(point(100, 0), point(100, 100)); scanf("%lf%lf",&dest.x, &dest.y); ans = 770; for(i=1;i<=n+2;i++) { cnt1 = cnt2 = 1; for(j=1;j<=n;j++) { if(seg_cross(s[j], dest, s[i].a))cnt1++; if(seg_cross(s[j], dest, s[i].b))cnt2++; } ans = min(min(cnt1, cnt2), ans); } printf("Number of doors = %d\n", ans); } return 0; }
相关文章推荐
- POJ 1066 Treasure Hunt 判断两线段是否相交
- POJ 1066 Treasure Hunt(线段相交判断)
- Treasure Hunt - POJ 1066(线段相交判断)
- Poj-1066 (判断线段与线段是否相交)
- POJ 1066 Treasure Hunt 判断线段相交(求交点个数)
- POJ 1066 Treasure Hunt 线段相交判断
- POJ 1066 Treasure Hunt(线段相交判断)
- POJ 1066 Treasure Hunt(线段相交判断)
- poj 1066 Treasure Hunt(判断线段相交)
- poj 1066 Treasure Hunt 线段相交判断
- POJ_1066_Treasure Hunt_判断线段相交
- poj 1066 Treasure Hunt(判断线段相交)
- poj 1066 Treasure Hunt(判断线段相交)
- Segments - POJ 3304 (判断直线与线段是否相交)
- Poj 1066 Treasure Hunt && Nyoj 83 迷宫寻宝(二)判断线段相交
- POJ 1066 Treasure Hunt (线段与线段相交) -
- poj 3304 Segments 【判断是否存在一条直线与所有线段相交】
- POJ 2653 Pick-up sticks 枚举判断线段是否相交
- poj 1410 Intersection 【判断线段 与矩形面是否相交】
- POJ 1066 Treasure Hunt [线段相交]【计算几何】