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

本题关键:如何找到最少的路径。

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

    思考很关键:从外围四个墙的某一个门进来,走到宝藏,最小走几个门,实际就是进门点和宝藏的连线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;
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值