POJ 4048 Chinese Repeating Crossbow(线段相交)

题目大意是:给你n条线段,和一个点然后让你求出以这个点为起点的射线最多可以与多少条线段相交。

思路:枚举每条线段的端点作为射线,然后在无穷远出取一个点连成线段,暴力枚举线段相交的个数。

Problem E. Chinese Repeating Crossbow 
Description 
In Chinese history, Zhuge Liang, prime minister of Shu in three kingdoms period, 
is regarded as the embodiment of wisdom. When he was dying he passed a book to 
his apprentice Jiang Wei privately. This book recorded the introduction and 
specification 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 Repeating Crossbow 
Later on, Jiang Wei 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 a 
direction, shot through as many straw walls as he can by his new weapon. 
The problem given to you is quite simple: assuming that the repeating crossbow 
can shot through any numbers 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's also 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. 
Input 
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]. 
Output 
For each test case, output a single integer representing the maximum number of straw walls can be shot through in one shot. 
Sample Input 


-1 -1 1 -1 
-1 1 1 1 
-1 2 1 2 
0 0 

-1 -1 1 -1 
-1 0 0 1 
1 0 0 1 
0 0 
Sample Output 

2

#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#define eps 1e-9
///#define M 1000100
#define LL __int64
///#define LL long long
#define INF 0x7ffffff
#define PI 3.1415926535898

const int maxn = 10100;

using namespace std;

struct point
{
    double x, y;
} p[maxn*2];

bool inter(point a, point b, point c, point d)
{
    if(min(a.x, b.x) > max(c.x, d.x) ||
            min(a.y, b.y) > max(c.y, d.y) ||
            min(c.x, d.x) > max(a.x, b.x) ||
            min(c.y, d.y) > max(a.y, b.y) )
        return 0;
    double h, i, j, k;
    h = (b.x-a.x)*(c.y-a.y) - (b.y-a.y)*(c.x-a.x);
    i = (b.x-a.x)*(d.y-a.y) - (b.y-a.y)*(d.x-a.x);
    j = (d.x-c.x)*(a.y-c.y) - (d.y-c.y)*(a.x-c.x);
    k = (d.x-c.x)*(b.y-c.y) - (d.y-c.y)*(b.x-c.x);
    return h*i <= eps && j*k <= eps;
}


int main()
{
    int T;
    cin >>T;
    double x, y;
    while(T--)
    {
        int n;
        cin >>n;
        for(int i = 1; i <= 2*n; i += 2)
            scanf("%lf %lf %lf %lf",&p[i].x, &p[i].y, &p[i+1].x, &p[i+1].y);
        scanf("%lf %lf",&x, &y);
        for(int i = 1; i <= 2*n; i += 2)
        {
            p[i].x -= x;
            p[i+1].x -= x;
            p[i].y -= y;
            p[i+1].y -= y;
        }
        LL Max = 0;
        LL ans = 0;
        LL cnt = 0;
        point f;
        f.x = 0;
        f.y = 0;
        for(int i = 1; i <= 2*n; i += 2)
        {
            ans = 0;
            point t = p[i];
            t.x *= 20000;
            t.y *= 20000;
            for(int j = 1; j <= 2*n; j += 2)
                if(inter(f, t, p[j], p[j+1]))
                    ans ++;
            cnt = 0;
            t = p[i+1];
            t.x *= 20000;
            t.y *= 20000;
            for(int j = 1; j <= 2*n; j += 2)
                if(inter(f, t, p[j], p[j+1]))
                   cnt ++;

            Max = max(ans, max(Max, cnt));
        }
        cout<<Max<<endl;
    }
    return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值