前端之家收集整理的这篇文章主要介绍了
poj 4048 计算几何(线段相交)金华邀请赛 E题,
前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
题意说是有个人在一个点o上,然后他拿了一个巨强的诸葛连弩,可以射穿任何东西,现在给你许多城墙(就是线段了),问你他朝那个方向射击会射穿最多的城墙,只要接触城墙就算是射穿了。
分析:计算几何,思路就是离散加枚举。枚举每点到o的射线,我们可在射线的无穷远处选一个点tp和o组成一个线段l。然后记录有多少条线段于l相交,取最大值。
#include <iostream>
#include <cstdio>
#include <cstring>
#define maxn 1600
#define infv 1e6
#define eps 1e-7
using namespace std;
struct node
{
double x,y;
}b[maxn],e[maxn],stand,inf;
int vb[maxn],ve[maxn];
int crossproduct(node base,node a,node b)//向量base->a与base->b的叉乘
{
double temp = (a.x - base.x) * (b.y -base.y) - (b.x - base.x) * (a.y - base.y);
if(temp <= -eps) return -1;
if(temp >= eps) return 1;
else return 0;
}
bool intersect(node a,node b,node c,node d)
{
//判断线段ab和线段cd相不相交
if(max(a.x,b.x) >= min(c.x,d.x) &&
max(a.y,b.y) >= min(c.y,d.y) &&
max(c.x,d.x) >= min(a.x,b.x) &&
max(c.y,d.y) >= min(a.y,b.y) &&
crossproduct(a,b,c) * crossproduct(a,d,b) >= 0 &&//大于等于0 //直线ab是否和cd相交
crossproduct(c,a,d) * crossproduct(c,b) >= 0 //直线cd是否和ab相交
)
return true;
return false;
}
int cases,n,ans,ret,alr;
bool judge(node a,node c)
{//枚举射线,因为intersection这个函数是判断线段和线段相交的
if(a.x == stand.x){//找无穷大的那个射线点
inf.x = stand.x;
if(stand.y > a.y)
inf.y = -infv;
else
inf.y = infv;
}
else
{
if(stand.x > a.x)
inf.x = -infv;
else
inf.x = infv;
inf.y = (a.y - stand.y) * (inf.x - stand.x) * 1.0 / (a.x - stand.x) + stand.y;
}
if( intersect(stand,inf,c) )
return true;
return false;
}
int main()
{
scanf("%d",&cases);
while(cases --){
scanf("%d",&n);
for(int i = 0; i < n; i ++){
scanf("%lf%lf%lf%lf",&b[i].x,& b[i].y,&e[i].x,& e[i].y);
}
scanf("%lf%lf",&stand.x,&stand.y);
memset(vb,sizeof(vb));
ret = 0;
memset(ve,sizeof(ve));
alr = 0;
for(int i = 0; i < n; i ++)
{
if(b[i].x == stand.x && b[i].y == stand.y)
{//判断是否和线段一个端点重合
vb[i] ++;
alr ++;
}
if(e[i].x == stand.x && e[i].y == stand.y)
{//判断是否和线段另一个端点重合
ve[i] ++;
alr ++;
}
}
for(int i = 0; i < n; i ++)
{
if(!vb[i])
{
ans = 0;
for(int j = 0; j < n; j ++)
{
if( judge(b[i],b[j],e[j]) )
ans ++;
}
if(ans > ret) ret = ans;
// cout << "s " << ans << endl;
}
if(!ve[i])
{
ans = 0;
for(int j = 0; j < n; j ++)
{
if(judge( e[i],e[j]) )
ans ++;
}
if(ans > ret) ret = ans;
// cout << "e " << ans << endl;
}
}
cout << ret + alr << endl;
}
return 0;
}