题意:有一个强大的弓弩,可以射穿所有障碍,给n(n<1=500)个墙,即n条线段,问弓弩朝一个方向可以射到的最多的墙的数量(擦着墙端也算为射到)。
解法:离散化所有的墙段点,以出发点为一端和每个墙端为另一端(加长到足够长),然后分别计算和多少线段非严相交。线段非严格相交的判定是:
1、严格相交(叉积判断)
2、点在线段上,这时叉积等于0并且点在线段之间
代码:
/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;
#define eps 1e-9
const double pi=acos(-1.0);
typedef long long LL;
const int Max=1600;
const int INF=1000000007;
int n;
struct point
{
double x,y;
};
struct edge
{
point a,b;
} edges[Max];
point aim;
double mult(point a,point b,point c)
{
b.x=a.x-b.x;
b.y=a.y-b.y;
c.x=a.x-c.x;
c.y=a.y-c.y;
double tool=b.x*c.y-b.y*c.x;
if(tool<-eps)
return -1.0;
if(tool>eps)
return 1.0;
return 0;
}
bool on_seg(point a,point b,point c)
{
return (a.x<=max(b.x,c.x)&&a.x>=min(b.x,c.x)
&&a.y<=max(b.y,c.y)&&a.y>=min(b.y,c.y)&&mult(a,b,c)==0);
}
bool OK(point a,point b,point c,point d)
{
if((mult(a,c,d)*mult(b,c,d)<0)&&(mult(c,a,b)*mult(d,a,b)<0))
return true;
if(on_seg(a,c,d)||on_seg(b,c,d)||on_seg(c,a,b)||on_seg(d,a,b))
return true;
return false;
}
int solve(point a,point b,int j)
{
point c;
c.x=b.x+(b.x-a.x)*10000.0;
c.y=b.y+(b.y-a.y)*10000.0;
//cout<<b.x<<" "<<b.y<<endl;
int res=1;
for(int i=0; i<n; i++)
{
if(i==j) continue;
if(OK(a,c,edges[i].a,edges[i].b))
res++;
}
return res;
}
int main()
{
int t;
cin>>t;
while(t--)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%lf%lf%lf%lf",&edges[i].a.x,&edges[i].a.y,&edges[i].b.x,&edges[i].b.y);
}
scanf("%lf%lf",&aim.x,&aim.y);
int ans=1;
for(int i=0; i<n; i++)
{
ans=max(ans,solve(aim,edges[i].a,i));
ans=max(ans,solve(aim,edges[i].b,i));
}
cout<<ans<<endl;
}
return 0;
}