zoukankan      html  css  js  c++  java
  • BZOJ 3007 [SDOI2012]拯救小云公主

    Solution

    答案具有单调性, 显然可以二分答案。

    有两个注意点 : 英雄是可以随便走的, 也就是不是网格图。。。 还有坐标不能小于$1$ QAQ

     

    开始时英雄在左下角, 公主在右上角, 我们反过来考虑, 让英雄不能到达公主那。

    把每个boss 看作是以其坐标为圆心, $mid$为半径的圆。

    这时必须满足条件  : 矩形的下边和 左边或上边能通过圆连接

            或者 矩形的 右边 和  左边或上边能通过圆连接。

    这样我们只需把 下边和右边看作一个点, 左边和上边看作一个点 , 用并查集合并能够通过圆连接的boss 和 边界。

    最后判断两个边界是否在同一集合内即可。

     

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #define R register
     5 #define rd read()
     6 using namespace std;
     7 
     8 const int N = 3e3 + 100;
     9 const double eps = 1e-4;
    10 const double EPS = 1e-6;
    11 
    12 int n, row, line;
    13 int S, T;
    14 int f[N];
    15 double Dis[N][N];
    16 
    17 struct node {
    18     int x, y;
    19 }pos[N];
    20 
    21 inline int read() {
    22     int X = 0, p = 1; char c = getchar();
    23     for(;c > '9' || c < '0'; c = getchar()) if(c == '-') p = -1;
    24     for(; c >= '0' && c <= '9'; c = getchar()) X = X * 10 + c - '0';
    25     return X * p;
    26 }
    27 
    28 int get(int x) {
    29     return f[x] == x ? x : f[x] = get(f[x]);
    30 }
    31 
    32 inline void merge(int x, int y) {
    33     x = get(x); y = get(y);
    34     f[x] = y;
    35 }
    36 
    37 inline double cal(int i, int j) {
    38     double x = pos[i].x - pos[j].x;
    39     double y = pos[i].y - pos[j].y;
    40     return sqrt(x * x + y * y);
    41 }
    42 
    43 bool jud(double dis) {
    44     for(R int i = 0; i <= n + 1; ++i)
    45         f[i] = i;
    46     for(R int i = 1; i <= n; ++i) 
    47         if(pos[i].x + dis + EPS >= row || pos[i].y - dis - EPS <= 1)
    48             merge(0, i);
    49     for(R int i = 1; i <= n; ++i)
    50         if(pos[i].x - dis - EPS <= 1 || pos[i].y + dis + EPS >= line)
    51             merge(i, n + 1);
    52     for(R int i = 1; i <= n; ++i)
    53         for(R int j = i + 1; j <= n; ++j) {
    54             int x = get(i), y = get(j);
    55             if(x == y) continue;
    56             if(Dis[i][j] <= 2 * dis)
    57                 merge(i, j);
    58         }
    59     return get(0) != get(n + 1);
    60 }
    61 
    62 int main()
    63 {
    64     n = rd; row = rd; line = rd;
    65     S = 0, T = n + 1;
    66     for(R int i = 1; i <= n; ++i)    pos[i].x = rd, pos[i].y = rd;
    67     for(R int i = 1; i <= n; ++i)
    68         for(R int j = i + 1; j <= n; ++j)
    69             Dis[i][j] = cal(i, j);
    70     double l = 0, r = row;
    71     int cnt = 60;
    72     if(line > row) r = line;
    73     while(l + eps < r && cnt--) {
    74         R double mid = (l + r) / 2;
    75         if(jud(mid)) l = mid;
    76         else r = mid;
    77     }
    78     printf("%.2lf
    ", l);
    79 }
    View Code
  • 相关阅读:
    游标、锁
    树形背包浅谈
    金字塔
    Codeforces Round #652 (Div. 2) 题解
    NOI1999 棋盘分割
    NEERC2002 Folding
    HDU4283 You Are the One
    Codeforces Round #646 (Div. 2) 题解
    洛谷 P1679 神奇的四次方数
    UVA12563 劲歌金曲
  • 原文地址:https://www.cnblogs.com/cychester/p/9654927.html
Copyright © 2011-2022 走看看