题目链接:点击查看
题意:从一给出的点出发可以向任意方向发出射线,然后现在平面上共有1500条线段,问最多能使射线和几条线段相交
题解:每个线段都有一个对应的角度范围,刚开始想的是离散化一下,求一下哪个范围包括的最多,但是对应的范围是一个360度的圈,没法操作,然后注意到了数据只有1500,这样就可以暴力所有的端点,枚举每一条线段判断是否相交即可,射线我们可以抽象成线段,先判断射线的方向,然后把另一端点x设成10000,或-10000 ,y坐标相似求一下即可
两线段相交模板:点击查看,用过好几次了,挺好用的,可以保存一下。
#include<iostream>
#include<cstdio>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=50010;
struct node{
int x1,y1,x2,y2;
}aa[1100];
struct node1{
int x,y;
}p[2100];
struct Point{
double x,y;
};
int n,len;
int xx,yy;
map<int,map<int,int> > mp;
bool judge(int i,int j)
{
Point a,b,c,d;
a.x=xx;
a.y=yy;
if(p[i].x==xx)
{
b.x=p[i].x;
if(p[i].y>yy) b.y=10000;
else b.y=-10000;
}
else if(p[i].x>xx)
{
b.x=10000;
b.y=(double)(10000.0-xx)/(p[i].x-xx)*(p[i].y-yy)+yy;
}
else
{
b.x=-10000;
b.y=(double)(xx+10000)/(xx-p[i].x)*(p[i].y-yy)+yy;
}
c.x=aa[j].x1;
c.y=aa[j].y1;
d.x=aa[j].x2;
d.y=aa[j].y2;
if(!(min(a.x,b.x)<=max(c.x,d.x) && min(c.y,d.y)<=max(a.y,b.y)&&min(c.x,d.x)<=max(a.x,b.x) && min(a.y,b.y)<=max(c.y,d.y)))
return false;
double u,v,w,z;
u=(c.x-a.x)*(b.y-a.y)-(b.x-a.x)*(c.y-a.y);
v=(d.x-a.x)*(b.y-a.y)-(b.x-a.x)*(d.y-a.y);
w=(a.x-c.x)*(d.y-c.y)-(d.x-c.x)*(a.y-c.y);
z=(b.x-c.x)*(d.y-c.y)-(d.x-c.x)*(b.y-c.y);
return (u*v<=0.00000001 && w*z<=0.00000001);
}
int main()
{
int T;
int x,y;
scanf("%d",&T);
while(T--)
{
len=0;
mp.clear();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d%d",&aa[i].x1,&aa[i].y1,&aa[i].x2,&aa[i].y2);
if(!mp[aa[i].x1][aa[i].y1])
{
mp[aa[i].x1][aa[i].y1]=1;
p[++len].x=aa[i].x1;
p[len].y=aa[i].y1;
}
if(!mp[aa[i].x2][aa[i].y2])
{
mp[aa[i].x2][aa[i].y2]=1;
p[++len].x=aa[i].x2;
p[len].y=aa[i].y2;
}
}
scanf("%d%d",&xx,&yy);
int ans=0;
for(int i=1;i<=len;i++)
{
int cnt=0;
for(int j=1;j<=n;j++)
if(judge(i,j))
cnt++;
ans=max(cnt,ans);
}
printf("%d\n",ans);
}
return 0;
}