题意说是有个人在一个点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; }