poj 3304 Segments
题意:给你100以内的n条线段,问你是否存在一条直线,使得题给的线段在这条直线上的“投影” 相交于一点;
思路:
1.先要将线段投影相交于一点转变为存在一条直线与所有的线段相交;
很自然的想到,当存在一条直线使得所有的线段的投影都相交于一点时,过这点与该直线垂直的直线必定与所有的直线相交;
2.如何判断这样的直线是否存在呢?
假设这样的直线存在,则这条直线的所能转动的极限位置就是与题目所给的线段的端点重合,这就直接枚举任意两条线段的两个端点;还有就是怎么知道所枚举出来的直线就与题给的线段相交呢?(重点)还是利用了叉乘的性质,前面TOYS那题,通过叉乘来判断出了点在线段的那一边,现在就直接判断两点(线段的端点)的叉积是否表示同时针即可~~~
3.注意特判。。。,就是因为没判断n == 1的情况,WA了几次2333
// 732K 32MS #include<iostream> #include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<map> #include<queue> #include<vector> #include<cmath> #include<stdlib.h> #include<time.h> using namespace std; #define MS0(a) memset(a,0,sizeof(a)) #define esp 1e-6 const int MAXN = 110; struct point{ double x,y; point(){} point(double _x,double _y){ x = _x; y = _y; } double operator *(const point &b)const{// 点向量叉乘 return (x*b.y - y*b.x); } point operator -(const point &b)const{ return point(x - b.x,y - b.y); } double dot(const point &b){ //点乘 return x*b.x + y*b.y; } double dist(const point &b){ return sqrt((x-b.x)*(x-b.x)+(y-b.y)*(y-b.y)); } double dist2(const point &b){ return (x-b.x)*(x-b.x)+(y-b.y)*(y-b.y); } double len(){ return sqrt(x*x+y*y); } double point_to_segment(point b,point c)//点a到“线段” bc的距离a.point_to_segment(b,c); { point v[4]; v[1] = {c.x - b.x,c.y - b.y}; v[2] = {x - b.x,y - b.y}; v[3] = {x - c.x,y - c.y}; if(v[1].dot(v[2]) < 0) return v[2].len(); if(v[1].dot(v[3]) > 0) return v[3].len(); return fabs(1.*(v[1]*v[2])/v[1].len()); } double Xmult(const point &b,const point &c){ // 当a->b与a->c顺时针转时,返回正; return (b-*this)*(c-*this); } bool operator <(const point &b)const{ return y < b.y||(fabs(y - b.y) < esp && x < b.x); } void input(){ scanf("%lf%lf",&x,&y); } }p[MAXN]; point s[MAXN],t[MAXN]; int n,tot; bool cmp(const point &a,const point &b) { return fabs(a.x - b.x) < esp && fabs(a.y - b.y) < esp; } bool solve(point U,point L) { if(cmp(U,L)) return false; for(int i = 1;i <= n;i++){ point a = s[i], b = t[i]; if(a.Xmult(U,L) * b.Xmult(U,L) > esp) return false; } return true; } int main() { int T,i,j,x1,y1,x2,y2; cin>>T; while(T--){ int flag = 0; scanf("%d",&n); for(i = 1;i <= n;i++){ s[i].input(); t[i].input(); } if(n < 3) flag = 1; // *** for(i = 1;i < n && !flag;i++){ for(j = i + 1;j <= n && !flag;j++){ if(solve(s[i],s[j])||solve(s[i],t[j])||solve(t[i],s[j])||solve(t[i],t[j])){ flag = 1; } } } puts(flag?"Yes!":"No!"); } return 0; }