P3297 [SDOI2013] escape test

Title Description

Gao test again, for speaking really not good news for not carefully reading Xiao Yang will seriously study at home, his relatives decided stationed at his house he supervised learning, grandparents, grandparents, uncle, sister, aunt ......

Xiao Yang is really intolerable, and this life with prison What is the difference! To his dear Little Red, for his dota, he decided to escape!

Yang assumed that the family is n * m matrix, the lower left corner coordinates (0, 0), the top right corner coordinates (xl, yl). Xiao Yang has n relatives stationed within the matrix (different position, and not on the edge of the matrix). Xiao Yang at home everywhere are relatives monitors, and only the closest relatives monitoring:

That it is assumed that the position where the Yang (3,3), the relative A (3,0), A 3 is the distance from Yang; relatives in B (6,7), the distance B is a distance Yang 5 . Distance A <distance B, so (3,3) A position indicated by monitoring.

If the "shortest distance" appears at the same time there are several relatives, so that position while being monitored and that several relatives.

Yang's coordinates are given (x0, y0). Because the fewer number of people to be found, the greater the chance of a successful escape, so Xiao Yang playing you need to design an escape route to the edge of the rectangle, and a minimum number of people to be found.

Ps: Yang done is arbitrary direction, i.e. an arbitrary position on the line for an H is playing a real number.

Xiao Yang is only a start to ensure a relative monitors.

Input Format

The first line of a positive integer t <= 3 represents the number of data

Next, data t:

The first line n represents the number of relatives

The second line four positive integer upper right corner coordinates (x1, y1) and coordinates Xiao Yang (x0, y0) held

Next n lines, each line indicates the position of two positive integers a relative of

Output Format

Each data a positive integer represents the minimum number of people were found to jailbreak

Sample input and output

Input # 1

2
4
10 10 5 5
5 6
3 5
7 5
5 3
17
14 12 7 6
7 11
6 9
7 7
1 10
2 20
1 6
2 6
1 1
2 2
5 1
5 2
13 1
12 2
12 7
13 7
12 11
13 11

Output # 1

1
2

Description / Tips

Data interpretation:

The first data, Xiao Yang directly go up, only to be (5,6) monitor too.

The second data, Xiao Yang is (7,7) Monitoring - went to (9,9) is (7,11) monitor, and then directly go up.

Data Scale:

Before 50% of the data n <= 200;

Remaining data n <= 600.

Determined relative to the perpendicular bisector of each other relatives of these perpendicular bisectors and a rectangular four weeks, a half plane cross constituting the convex hull

Each half-plane cross-determined, then with his relatives and even adjacent side, the right side is 1, the shortest run,

This question is focusing on the construction drawing, which is calculated for each jurisdiction relatives

note

1. Some relatives outside the rectangle

2. The special judge what \ (n = 0 \) case

3. The intersection of the demand function, must think about it, it is impossible to remember,

inline point meetline(Line A , Line B)
{
    if(dcmp(cross(A.v , B.v)) == 0) return (point){0 , 0};
    point k = A.p - B.p;
    return A.p + A.v * (cross(B.v , k) / cross(A.v , B.v));
}

The former minus the latter

The former returned by the scale, the latter ratio is the ratio of the total area * k

4.onright function

Incoming cross the endpoint direction of a line rather than a straight line

return dcmp(cross(A - B.p , B.v))// AC 
return dcmp(cross(A - B.p , B.p))// WA 

5. Note that the determination condition is used to \ (IF \) or \ (Continue \) of

if(no[i] || j == i) countinue;
if(!no[i] && j != i) { do .... }
6. Multi-measure cleared

Note the type of parameters passed dcmp must necessarily be double

In short, attention to detail! !

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int N = 1000;
const double eps = 1e-8;
inline int read()
{
    register int x = 0; register char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
    return x;
}
int n , X0 , Y0 , X1 , Y1 , s , tot , cnt;
int head[N] , no[N];
struct edge{int v , nex;} e[N*N];
inline int dcmp(double x) { return fabs(x) < eps ? 0 : (x < 0 ? -1 : 1); }
void add(int u , int v) 
{ 
    e[++cnt].v = v; e[cnt].nex = head[u]; head[u] = cnt;
    e[++cnt].v = u; e[cnt].nex = head[v]; head[v] = cnt;
    return ;
}
struct point{
    double x , y;
    point(double x = 0 , double y = 0) : x(x) , y(y) {}
    point operator + (const point &A) const {return point(x + A.x , y + A.y);}
    point operator - (const point &A) const {return point(x - A.x , y - A.y);}
    point operator * (const double &K) const { return point(x * K , y * K); }
    double operator * (const point &A) const {return x * A.x + y * A.y; }
}a[N] , p[N];

struct Line{
    point p , v; int id; double ang;
    Line(point p = point() , point v = point() , int id = 0): p(p) , v(v), id(id) { ang = atan2(v.y , v.x); }
    bool operator < (const Line &A) const { return ang < A.ang; }
}l[N] , sta[N];

double cross(point A , point B) { return A.x * B.y - A.y * B.x; }
double dot(point A) { return A.x * A.x + A.y * A.y; }
double dis(point A , point B) { return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));}
inline bool onright(point A , Line B) { return dcmp(cross(A - B.p , B.v)) > 0; } // !!!!
inline point meetline(Line A , Line B)
{
    if(dcmp(cross(A.v , B.v)) == 0) return (point){0 , 0};
    point k = A.p - B.p;
    return A.p + A.v * (cross(B.v , k) / cross(A.v , B.v));
}

point rot(point A) { return point(-A.y , A.x); }
Line get_mid_line(point A , point B , int i) // A 和 B 的垂直平分线
{
    point p = point((A.x + B.x) / 2 , (A.y + B.y) / 2);
    return Line(p , rot(B - A) , i);
}

void init(int id)
{
    tot = 0;
    l[++tot] = Line(point(0 , 0) , point(1 , 0) , n + 1);
    l[++tot] = Line(point(X1 , 0) , point(0 , 1) , n + 1);
    l[++tot] = Line(point(X1 , Y1) , point(-1 , 0) , n + 1);
    l[++tot] = Line(point(0 , Y1) , point(0 , -1) , n + 1);
    for(int i = 1 ; i <= n ; ++i) if(i != id && !no[i]) // !!!
        l[++tot] = get_mid_line(a[id] , a[i] , i);
    return ;
}

void calc(int id)
{
    int n = tot , tail , head;
    sort(l + 1 , l + 1 + n); sta[head = tail = 1] = l[1];
    for(int i = 2 ; i <= n ; ++i)
    {
        while(head < tail && onright(p[tail-1] , l[i])) tail--;
        while(head < tail && onright(p[head] , l[i])) head++;
        sta[++tail] = l[i];
        if(dcmp(cross(sta[tail].v , sta[tail-1].v)) == 0)
        {
            tail--;
            if(onright(sta[tail].p , l[i])) sta[tail] = l[i];
        }
        if(head < tail) p[tail-1] = meetline(sta[tail] , sta[tail-1]);
    }
    while(head < tail && onright(p[tail-1] , sta[head])) tail--;
    if(head >= tail) return ;
    p[tail] = meetline(sta[head] , sta[tail]);
    for(int i = head ; i <= tail ; ++i) add(id , sta[i].id);
    return ;
}

int d[N] , vis[N];
int spfa(int s)
{
    queue<int> q; q.push(s);
    for(int i = 1 ; i <= n + 1 ; ++i) d[i] = 1e9 , vis[i] = 0;
    d[s] = 0;
    while(q.size())
    {
        int x = q.front(); q.pop(); vis[x] = 0;
        for(int i = head[x] ; i ; i = e[i].nex)
        {
            int v = e[i].v;
            if(d[v] > d[x] + 1)
            {
                d[v] = d[x] + 1;
                if(!vis[v]) vis[v] = 1 , q.push(v);
            }
        }
    }
    return d[n+1];
}

void clear() // 多测清空
{
    memset(head , 0 , sizeof head); cnt = 0;
    memset(no , 0 , sizeof no);
    return ;
}

int main()
{
    int T = read();
    while(T --> 0)
    {
        n = read();
        X1 = read(); Y1 = read(); X0 = read(); Y0 = read();
        if(n == 0) { puts("0"); continue; }
        double minn = 1e50 , len = 1e50;
        for(int i = 1 , x , y ; i <= n ; ++i)
        {
            x = read() , y = read() , a[i] = point(1.0 * x , 1.0 * y);
            if(x > X1 || y > Y1) no[i] = 1;
            len = dis(a[i] , point(X0 , Y0));
            if(len < minn) minn = len , s = i;
        }
        //printf("---------------------\n%d\n--------------------------\n" , s);
        for(int i = 1 ; i <= n ; ++i)
        {
            if(no[i]) continue;
            init(i); calc(i);
        }
        printf("%d\n" , spfa(s));
        clear();
    }
    return 0;
}
/*
2
4
10 10 5 5
5 6
3 5
7 5
5 3
17
14 12 7 6
7 11
6 9
7 7
1 10
2 20
1 6
2 6
1 1
2 2
5 1
5 2
13 1
12 2
12 7
13 7
12 11
13 11
 */

Guess you like

Origin www.cnblogs.com/R-Q-R-Q/p/12149359.html