• BZOJ1822 Frozen Nova 冷冻波


    1822: [JSOI2010]Frozen Nova 冷冻波

    Time Limit: 10 Sec  Memory Limit: 64 MB

    Description

    WJJ喜欢“魔兽争霸”这个游戏。在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵。我们认为,巫妖和小精灵都可以看成是平面上的点。 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵。 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放。不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以杀死一个小精灵。 现在巫妖的头目想知道,若从0时刻开始计算,至少需要花费多少时间,可以杀死所有的小精灵?

    Input

    输入文件第一行包含三个整数N、M、K(N,M,K<=200),分别代表巫妖的数量、小精灵的数量和树木的数量。 接下来N行,每行包含四个整数x, y, r, t,分别代表了每个巫妖的坐标、攻击范围和施法间隔(单位为秒)。 再接下来M行,每行两个整数x, y,分别代表了每个小精灵的坐标。 再接下来K行,每行三个整数x, y, r,分别代表了每个树木的坐标。 输入数据中所有坐标范围绝对值不超过10000,半径和施法间隔不超过20000。

    Output

    输出一行,为消灭所有小精灵的最短时间(以秒计算)。如果永远无法消灭所有的小精灵,则输出-1。

    Sample Input

    2 3 1
    -100 0 100 3
    100 0 100 5
    -100 -10
    100 10
    110 11
    5 5 10

    Sample Output

    5

    Source

    JSOI2010第二轮Contest1


    题解

    网络流 + 二分答案 + 计算几何

    计算几何用点积和叉积计算点到线段距离,二分所需时间,网络流验证是否可行

    大水题,数据有点坑qwq

    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 template <class _T> inline void read(_T &_x) {
      4     int _t; bool flag = false;
      5     while ((_t = getchar()) != '-' && (_t < '0' || _t > '9')) ;
      6     if (_t == '-') _t = getchar(), flag = true; _x = _t - '0';
      7     while ((_t = getchar()) >= '0' && _t <= '9') _x = _x * 10 + _t - '0';
      8     if (flag) _x = -_x;
      9 }
     10 typedef long long LL;
     11 const int maxn = 1010;
     12 const int maxm = 100010;
     13 const double eps = 1e-8;
     14 inline int sign(double val) {return val < -eps ? -1 : val > eps; }
     15 struct Point {
     16     double x, y;
     17     Point (double a = 0, double b = 0):x(a), y(b) {}
     18 }A[maxn], B[maxn], C[maxn];
     19 double rA[maxn], rC[maxn];
     20 double dot(Point a, Point b, Point c) {
     21     return (b.x - a.x) * (c.x - a.x) + (b.y - a.y) * (c.y - a.y);
     22 }
     23 double cross(Point a, Point b, Point c) {
     24     return (b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y);
     25 }
     26 double dist(Point a, Point b) {
     27     return hypot(a.x - b.x, a.y - b.y);
     28 }
     29 double ldis(Point a, Point b, Point c) {
     30     if (dot(c, a, b) > 0) return min(dist(a, c), dist(b, c));
     31     return fabs(cross(a, b, c) / dist(a, b));
     32 }
     33 bool check(Point a, Point b, Point c, int pc) {
     34     double dis = dist(a, b), r = dot(a, b, c) / dis;
     35     if (r < 0 || r > dis) return true;
     36     return sign(fabs(cross(a, b, c) / r) - rC[pc]) > 0;
     37 }
     38 struct Edge {
     39     int v, flow, nxt;
     40     Edge () {}
     41     Edge (int a, int b, int c):v(a), flow(b), nxt(c) {}
     42 }e[maxm];
     43 int n, m, k, t[maxn], sink;
     44 int fir[maxn], tag[maxn], cur[maxn], ecnt;
     45 bool can[maxn][maxn];
     46 inline void addedge (int a, int b, int c) {
     47     e[++ecnt] = Edge (b, c, fir[a]), fir[a] = ecnt;
     48     e[++ecnt] = Edge (a, 0, fir[b]), fir[b] = ecnt;
     49 }
     50 inline bool bfs() {
     51     memset(tag, 0, sizeof (int) * (sink + 1));
     52     queue<int> q; q.push(0), tag[0] = 1;
     53     while (!q.empty()) {
     54         int now = q.front(); q.pop();
     55         for (int u = fir[now]; u; u = e[u].nxt) {
     56             if (e[u].flow && !tag[e[u].v]) {
     57                 tag[e[u].v] = tag[now] + 1;
     58                 q.push(e[u].v);
     59             }
     60         }
     61     }
     62     return tag[sink] != 0;
     63 }
     64 int dfs(int now, int flow) {
     65     if (now == sink) return flow;
     66     int usd = 0;
     67     for (int &u = cur[now]; u; u = e[u].nxt) {
     68         if (e[u].flow && tag[e[u].v] > tag[now]) {
     69             int ret = dfs(e[u].v, min(e[u].flow, flow - usd));
     70             if (ret) {
     71                 e[u].flow -= ret;
     72                 e[u ^ 1].flow += ret;
     73                 usd += ret;
     74                 if (usd == flow) return flow;
     75             }
     76         }
     77     }
     78     return usd;
     79 }
     80 inline int dinic() {
     81     int flow = 0;
     82     while (bfs()) {
     83         for (int i = 0; i <= sink; ++i) cur[i] = fir[i];
     84         flow += dfs(0, m);
     85     }
     86     return flow;
     87 }
     88 bool check(int tim) {
     89     memset(fir, 0, sizeof (int) * (sink + 1));
     90     ecnt = 1;
     91     for (int i = 1; i <= n; ++i) {
     92         addedge(0, i, tim / t[i] + 1);
     93         for (int j = 1; j <= m; ++j) if (can[i][j]) {
     94             addedge(i, n + j, 1);
     95         }
     96     }
     97     for (int i = 1; i <= m; ++i) addedge(n + i, sink, 1);
     98     return dinic() >= m;
     99 }
    100 int main() {
    101     //freopen(".in", "r", stdin);
    102     //freopen(".out", "w", stdout);
    103     read(n), read(m), read(k);
    104     for (int i = 1; i <= n; ++i) {
    105         scanf("%lf%lf%lf%d", &A[i].x, &A[i].y, &rA[i], &t[i]);
    106     }
    107     for (int i = 1; i <= m; ++i) {
    108         scanf("%lf%lf", &B[i].x, &B[i].y);
    109     }
    110     for (int i = 1; i <= k; ++i) {
    111         scanf("%lf%lf%lf", &C[i].x, &C[i].y, &rC[i]);
    112     }
    113     for (int i = 1; i <= n; ++i) {
    114         for (int j = 1; j <= m; ++j) {
    115             bool flag = true;
    116             double dis = dist(A[i], B[j]);
    117             if (dis > rA[i]) continue;
    118             for (int x = 1; x <= k; ++x) {
    119                 if (ldis(A[i], B[j], C[x]) < rC[x]) {
    120                     flag = false;
    121                     break;
    122                 }
    123             }
    124             if (flag) can[i][j] = true;
    125         }
    126     }
    127     for (int i = 1; i <= m; ++i) {
    128         bool flag = false;
    129         for (int j = 1; j <= n; ++j) if (can[j][i]) {
    130             flag = true; break;
    131         }
    132         if (!flag) {
    133             puts("-1");
    134             return 0;
    135         }
    136     }
    137     sink = n + m + 1;
    138     int l = 0, r = 20000 * m, mid;
    139     while (l < r) {
    140         if (check(mid = (l + r) >> 1)) r = mid;
    141         else l = mid + 1;
    142     }
    143     cout << l << endl;
    144     return 0;
    145 }
    View Code
  • 相关阅读:
    selenium iframe切换
    roboframework环境搭建与使用
    ServHa双机热备简单配置
    linux搭建java ee开发环境
    FPGA学习笔记(五)—— 组合逻辑电路设计
    FPGA学习笔记(三)—— 数字逻辑设计基础(抽象的艺术)
    FPGA学习笔记(一)——初识FPGA
    FPGA学习笔记(二)——FPGA学习路线及开发流程
    【js重学系列】异步编程
    【js重学系列】作用域
  • 原文地址:https://www.cnblogs.com/akhpl/p/6719594.html
Copyright © 2020-2023  润新知