题目大意:
就是现在从一点出发可以向任意方向发出射线,然后现在平面上共有1500条线段,问最多能使射线和几条线段相交。
大致思路:
很明显可以看出最优解在起点和线段的端点的连线上一定存在。
枚举2*线段条数条射线判断和线段的相交情况即可,复杂度O(n^2)完全可以接受,剩下的就是判断线段和射线相交的问题了,我用的是直线的参数方程,解出射线的参数 t1 >= 0,线段的参数 t2 >= 0 && t2 <= 1即可相交,另外注意射线和线段有重合部分的情况即可。
代码如下:
Result : Accepted Memory : 712 KB Time : 250 ms
/* * Author: Gatevin * Created Time: 2014/11/13 14:09:42 * File Name: A.cpp */ #include<iostream> #include<sstream> #include<fstream> #include<vector> #include<list> #include<deque> #include<queue> #include<stack> #include<map> #include<set> #include<bitset> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cctype> #include<cmath> #include<ctime> #include<iomanip> using namespace std; const double eps(1e-8); typedef long long lint; int sgn(double d) { return d < -eps ? -1 : (d > eps ? 1 : 0); } struct segment { double x1, y1, x2, y2; segment(double x0 = 0, double y0 = 0, double x00 = 0, double y00 = 0) { x1 = x0; y1 = y0; x2 = x00; y2 = y00; } void input() { scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2); } }; struct point { double x, y; point(double _x = 0, double _y = 0) { x = _x; y = _y; } }; typedef point Vector; int n; segment p[1510]; int ans; bool inter(double sx, double sy, Vector v1, double ex, double ey, Vector v2) { if(sgn(v1.y*v2.x - v1.x*v2.y) == 0)//射线与线段方向向量平行 { double t = (ex - sx)/v1.x; if(sgn(t) != -1 && sgn(t - (ey - sy)/v1.y) == 0) return true; t = (ex + v2.x - sx)/v1.x; if(sgn(t) != -1 && sgn(t - (ey + v2.y - sy)/v1.y) == 0) return true; return false; } double t2 = (v1.x*ey + v1.y*sx - v1.x*sy - v1.y*ex) / (v1.y*v2.x - v1.x*v2.y); double t1 = (ey*v2.x - sy*v2.x - v2.y*ex + sx*v2.y) / (v1.y*v2.x - v1.x*v2.y); //cout<<sx<<" "<<sy<<" "<<v1.x<<" "<<v1.y<<" "<<ex<<" "<<ey<<" "<<v2.x<<" "<<v2.y<<endl; //cout<<t1<<" "<<t2<<endl; if(sgn(t2 - 1.0) != 1 && sgn(t2) != -1 && sgn(t1) != -1) return true; return false; } void check(double sx, double sy, double ex, double ey)//射线起点(sx, sy), v1为方向向量 { Vector v1(ex - sx, ey - sy); int tmp = 0; for(int i = 1; i <= n; i++) { Vector v2(p[i].x2 - p[i].x1, p[i].y2 - p[i].y1); if(inter(sx, sy, v1, p[i].x1, p[i].y1, v2)) tmp++; } ans = max(ans, tmp); return; } int main() { int t; double sx, sy; scanf("%d", &t); while(t--) { ans = 0; scanf("%d", &n); for(int i = 1; i <= n; i++) p[i].input(); scanf("%lf %lf", &sx, &sy); for(int i = 1; i <= n; i++)//枚举射线 { check(sx, sy, p[i].x1, p[i].y1); check(sx, sy, p[i].x2, p[i].y2); } printf("%d\n", ans); } return 0; }