Openjudge5137 Chinese Repeating Crossbow(计算几何)

总时间限制: 
1000ms 
内存限制: 
65536kB
描述

In Chinese history, Zhuge Liang, prime minister of Shu in three kingdoms period, isregarded as the embodiment of wisdom. When he was dying he passed a book to his apprentice Jiang Wei privately. This book recorded the introduction andspecification of a most powerful weapon at that time, called Chinese repeating crossbow or Zhuge repeating crossbow (Figure 1). This weapon can shoot many arrows in a very short time and makes enemies very hard to defense it.


                   Figure 1 Chinese RepeatingCrossbow

Later on, JiangWei built a repeating crossbow according to the book and he wanted to know exactly about its power. He came to the center of a test field. The test field was ragged with several extreme high straw walls. Jiang Wei wanted to choose adirection, shot through as many straw walls as he can by his new weapon.

The problem given toyou is quite simple: assuming that the repeating crossbow can shot through anynumbers of straw walls, please help Jiang Wei to choose a certain direction that he can shot through maximum number of walls in one shot. The walls can be considered as line segments, and if an arrow touches the end points of a wall, it'salso called "shoot through". The straw walls can intersect or overlap with each other, and Jiang Wei may possibly stand extremely close to one of the straw wall.

输入
The first line of the input contains an integer T (T <= 10) representing the number of test cases.
In each test case, the first line contains an integer N (0 < N <= 1500) representing the number of straw walls on the field. Each of the following N lines contains four integer numbers x1, y1, x2, y2,which describes the end point (x1, y1) and (x2, y2) of a straw wall. The last line of the test case contains two integer (x, y) representing the position of Jiang Wei. All the coordinates are integer numbers and in the range of [-10000, 10000].
输出
For each test case, output a single integer representing the maximum number of straw walls can be shot through in one shot.
样例输入
23-1 -1 1 -1-1 1 1 1-1 2 1 20 03-1 -1 1 -1-1 0 0 11 0 0 10 0
样例输出
22



没想到gw布置的作业第三题就这样难度了= =,怪自己没学计算几何,直接搬别人代码了大哭


问你朝哪个方向设子弹穿过的墙最多~


两种方法的题解:点击打开链接


AC代码:


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define eps (1e-6)
int dblcmp(double a)
{
    if(fabs(a)<eps) return 0;
    return a>0?1:-1;
}
struct Point
{
    double x,y;
    Point(){}
    Point(double a,double b){x=a;y=b;}
};
struct Line
{
    Point x,y;
    Line(){}
    Line(Point a,Point b){x=a;y=b;}
}data[2000];
double dot(double x1,double y1,double x2,double y2)
{
    return x1*x2+y1*y2;
}
double dotdet(Point a,Point b,Point c)
{
    return dot(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
int betweenCmp(Point a,Point b,Point c)
{
    return dblcmp(dotdet(a,b,c));
}
double det(double x1,double y1,double x2,double y2)
{
    return x1*y2-x2*y1;
}
double cross(Point a,Point b,Point c)
{
    return det(b.x-a.x,b.y-a.y,c.x-a.x,c.y-a.y);
}
int segCross(Point a,Point b,Point c,Point d,Point &p)
{
    double s1,s2,s3,s4;
    int d1,d2,d3,d4;
    d1=dblcmp(s1=cross(a,b,c));
    d2=dblcmp(s2=cross(a,b,d));
    d3=dblcmp(s3=cross(c,d,a));
    d4=dblcmp(s4=cross(c,d,b));
    if((d1^d2)==-2&&(d3^d4)==-2)
    {
        p.x=(c.x*s2-d.x*s1)/(s2-s1);
        p.y=(c.y*s2-d.y*s1)/(s2-s1);
        return 1;
    }
    if((d1==0&&betweenCmp(c,a,b)<=0)||
        (d2==0&&betweenCmp(d,a,b)<=0)||
        (d3==0&&betweenCmp(a,c,d)<=0)||
        (d4==0&&betweenCmp(b,c,d)<=0))
        return 2;
    return 0;
}
bool judge(Point a,Point b,Line line,Point &p)
{
    Point tmp;
    tmp.x=b.x-a.x;    tmp.y=b.y-a.y;
    tmp.x=tmp.x*10000+a.x;
    tmp.y=tmp.y*10000+a.y;
    return segCross(a,tmp,line.x,line.y,p);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n;
        Point o;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            double a,b,c,d;
            scanf("%lf%lf%lf%lf",&a,&b,&c,&d);
            data[i]=Line(Point(a,b),Point(c,d));
        }
        scanf("%lf%lf",&o.x,&o.y);
        int res=0;
        for(int i=0;i<n;i++)
        {
            Point p;
            int cnt1=0,cnt2=0;
            for(int j=0;j<n;j++)
            {
                if(judge(o,data[i].x,data[j],p)) cnt1++;
                if(judge(o,data[i].y,data[j],p)) cnt2++;
            }
            res=max(res,max(cnt1,cnt2));
        }
        printf("%d\n",res);
    }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值