P3297 [SDOI2013]エスケープテスト

タイトル説明

ガオテストは再び、慎重に真剣に自宅で勉強しますシャオヤンを読んでいないため、本当によくないニュースを話すために、彼の親戚は、彼は教師あり学習彼の家に駐留決め、祖父母、祖父母、叔父、姉、叔母......

シャオヤンは本当に耐え難いあり、そして刑務所でこの人生はどのような違いです!彼の愛するリトルレッドに、彼のDOTAのために、彼は脱出することにしました!

ヤンは、家族がnであると仮定* M行列、左下隅の座標(0,0)、右上の座標(XL、イル)。シャオヤン(行列のエッジ上の異なる位置、およびいない)マトリックス内に常駐N親族を有します。シャオヤンは自宅でどこでも親戚のモニター、および監視のみ、最も近い親戚です。

親戚Bに(6,7)、距離Bは距離がヤン5である;ヤン(3,3)、相対A(3,0)は、A 3は、ヤンからの距離である位置と仮定されていること。距離A <距離Bは、そう(3,3)Aの位置が監視することによって示されます。

「最短距離」が表示された場合は、同時に複数の親族があり、その位置に監視されながら、そのいくつかの親戚という。

ヤンの座標は(X0、Y0)が与えられました。発見される人の数が少ないので、成功した脱出のチャンスが大きい、シャオヤンがあなたをプレイので、長方形のエッジ、および発見される人々の最小数に逃げ道を設計する必要があります。

PS:行うヤンは任意の方向、実数を再生しているHのためにライン上の、すなわち任意の位置です。

シャオヤンは、相対的なモニタを確保するための唯一のスタートです。

入力形式

正の整数、T <= 3の最初の行はデータの数を表します

次に、データt:

最初の行は、n親戚の数を表します。

第二直列4の正の整数右上隅の座標(x1、y1)と、座標シャオヤン(X0、Y0)が保持されています

次のn行は、各行は2つの正の整数の相対位置を示します

出力フォーマット

正の整数は、人々の最小数を表し、各データは脱獄に発見されました

サンプル入力と出力

入力#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

出力#1

1
2

説明/ヒント

データの解釈:

最初のデータは、シャオヤンは直接のみ(5,6)モニターすぎであることを、上がります。

監視シャオヤンは第二のデータ、(7,7) - (9,9)に行ってきました(7,11)のモニタで、その後、直接上がります。

データスケール:

データの50%前のn <= 200。

データを残りのn <= 600。

これらの垂直二等分線と長方形の4週間互いに親族の垂直二等分線、凸包を構成する半平面断面に対して決定

各半平面の交差判定は、その後、彼の親戚、さらに隣接する側で、右側は、最短ラン1

この質問は、各管轄親戚のために計算された構造図、に焦点を当てています

ご注意ください

矩形の外側1.いくつかの親戚

2.特別判事何\(n = 0の\)の場合

3.需要関数の交点、覚えておくことは不可能であり、それについて考える必要があり、

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));
}

元マイナス後者

前者はK *後者の比率は総面積の比率であり、スケールによって返さ

4.onright機能

直線ではなく、ラインの終点方向を横断着信

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

決意条件をするために使用される5注意(IF \)\または\(\続行)

if(no[i] || j == i) countinue;
if(!no[i] && j != i) { do .... }
6.マルチ尺度はクリア

必ずしも二重にする必要がありDCMP渡されたパラメータの種類に注意してください。

要するに、細部へのこだわり!

#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
 */

おすすめ

転載: www.cnblogs.com/R-Q-R-Q/p/12149359.html