POJ 4048 Chinese Repeating Crossbow(線段相交)

畫船聽雨發表於2014-07-08

題目大意是:給你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;
}


相關文章