hdu 3492 && hdu 3304

两道一样的题, 求: 给n条线段, 是否存在一条直线与这写线段都相交 !

 

首先来分析一下pku 3304:假如存在一条直线与所有的线段都相交, 那么朝直线的一侧平移,直到遇到一条线段的端点, 然后固定这个端点朝一个方向旋转与另外一条直线的端点相交, 那么此时就是一个临界状态呢, 在往前旋转一点就不满足要求了, 那么经过这样操作得来直线一定与所有线段相交。。。  

然后接着分析下,hdu 3492 , 题意有点偏差:求是否存在一条直线, 使得所有线段在其上面的投影不为空集。

做如下转换: 不为空集,就是至少存在一个交点。 那么我们假设有一条直线与所有线段相交, 那么我们做这条直线的垂直线, 那么垂足不就是所有直线在该直线上的一个映射点, 也就是交集不为空了, 那么就转化到了pku 3304 ,但后这题有个trick : 所有的点都是相同的。。

贴下代码:

/* hdu 2492*/ #include #include using namespace std ; #define N 310 #define eps 1e-8 struct point { double x, y ; }; struct Tpoint { point a, b ; void input() { scanf("%lf %lf %lf %lf", &a.x, &a.y, &b.x, &b.y) ; } bool equal() { return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)) <= eps ; } }seg[N], tmp ; int n ; bool Tsame ; int sign(double x) { if(fabs(x) <= eps ) return 0 ; if(x > 0) return 1 ; return -1 ; } double multiply(point p1, point p2, point p3) { return (p3.x - p1.x) * (p2.y - p1.y) - (p2.x - p1.x) * (p3.y - p1.y) ; } bool Insect(Tpoint u, Tpoint v) { double d3 = multiply(u.a, u.b, v.a) ; double d4 = multiply(u.a, u.b, v.b) ; if (sign(d3) * sign(d4) < 0 || sign(d3) == 0 || sign(d4) == 0) return true ; return false ; } bool check(point a, point b) { Tpoint tmp ; tmp.a = a, tmp.b = b ; if(tmp.equal()) return false ; Tsame = false ; for(int i = 0 ; i < n; i ++) { if(!Insect(tmp, seg[i])) return false ; } return true ; } int main() { int ncas ; scanf("%d", &ncas) ; while(ncas --) { scanf("%d", &n) ; for(int i = 0 ; i < n ; i ++) seg[i].input() ; if(n < 3) {/* 这里 开始忽略了 只有一条直线的情况 wa了 好几次。。。*/ puts("Yes") ; continue ; } bool flag = false ; Tsame = true ; for(int i = 0 ; i < n && !flag ; i ++) { for(int j = i+1 ; j < n && !flag ; j ++) { if( check(seg[i].a,seg[j].a) || check(seg[i].a,seg[j].b) || check(seg[i].b,seg[j].a) || check(seg[i].b,seg[j].b) ) flag = true ; } } if(Tsame) { puts("Yes") ; continue ; } puts(flag ? "Yes" : "No") ; } return 0 ; }

   

你可能感兴趣的:(数学,struct,input)