您的位置:首页 > 其它

POJ 1066 Treasure Hunt 判断两线段是否相交

2013-08-29 10:34 369 查看
本题关键:如何找到最少的路径。

刚刚做的一题计算几何时建图的,做到这道题,第一个想法就是建图,找最短路, 后来细想操作太多太繁琐,不好做, 所以放弃了,觉得应该有简单的做法。

    思考很关键:从外围四个墙的某一个门进来,走到宝藏,最小走几个门,实际就是进门点和宝藏的连线goalLine穿过几个点。

证明不好证,但如果说明大体的思想其实挺简单的:思想有点像两点之间直线最短。不要去管纵横交错的小线段,只管一开始原始输入的线段,因为在正方形范围内,这些线段可以想象为无限长,进门的点和宝藏点中间横跨着k条直线(墙 ),你就无法绕过它们,只能穿过它们 ,你往左往右走都只会徒增加你要穿过的墙,就这最基本的k道墙你总是要穿过。 

但这样做还是很麻烦,枚举每个中点毕竟还是很繁琐的,再仔细想想,能不能枚举每个边缘的端点呢,画了很多种情况,觉得应该还是可以的,敲了一遍, 结果 AC,哈哈;

思考真的狠关键,千万别偷懒,如果想偷懒,还不如不搞ACM,假如你做一道题,没有思路之前就不必敲键盘了,这会是无用功,思考真的很重要,毕竟算法和模板大家学的都是一样的。 




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;
}


 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: