【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流
题目描述
WJJ喜欢“魔兽争霸”这个游戏。在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵。我们认为,巫妖和小精灵都可以看成是平面上的点。 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵。 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放。不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以杀死一个小精灵。 现在巫妖的头目想知道,若从0时刻开始计算,至少需要花费多少时间,可以杀死所有的小精灵?
输入
输入文件第一行包含三个整数N、M、K(N,M,K<=200),分别代表巫妖的数量、小精灵的数量和树木的数量。 接下来N行,每行包含四个整数x, y, r, t,分别代表了每个巫妖的坐标、攻击范围和施法间隔(单位为秒)。 再接下来M行,每行两个整数x, y,分别代表了每个小精灵的坐标。 再接下来K行,每行三个整数x, y, r,分别代表了每个树木的坐标。 输入数据中所有坐标范围绝对值不超过10000,半径和施法间隔不超过20000。
输出
输出一行,为消灭所有小精灵的最短时间(以秒计算)。如果永远无法消灭所有的小精灵,则输出-1。
样例输入
2 3 1
-100 0 100 3
100 0 100 5
-100 -10
100 10
110 11
5 5 10
样例输出
5
题解
计算几何+二分+网络流最大流
首先要解决的是是否能够攻击到,如果两个点形成的线段与所有圆都没有公共点,那么就可以攻击到。
线段与圆有公共点,需要满足两个条件之一:(1)线段某端点在圆内 (2)直线与圆有公共点,且以线段和端点与圆心连线的夹角是锐角。
其中直线与圆有公共点可以使用点到直线距离公式:$\frac{|ax_0+by_0+c|}{\sqrt{a^2+b^2}}$,夹角是锐角可以使用余弦定理的推论:如果$a^2<b^2+c^2$,那么$A$是锐角。
判断完以后就是经典的二分+最大流判断问题了:二分时间,S向巫妖连边,容量为mid时间攻击次数;巫妖向能够攻击到的小精灵连边,容量为1;小精灵向T连边,容量为1。如果满流则mid可行,否则不可行。
注意攻击次数的计算公式:$\lfloor\frac{mid}t\rfloor+1$,即开场是没有冷却的。(为这个问题纠结了半天= =)
#include <queue> #include <cstdio> #include <cstring> #define N 410 #define M 200010 using namespace std; typedef long long ll; queue<int> q; ll xn[N] , yn[N] , rn[N] , tn[N] , xm[N] , ym[N] , xk[N] , yk[N] , rk[N]; int n , m , k , v[N][N] , head[N] , to[M] , val[M] , next[M] , cnt , s , t , dis[N]; inline ll squ(ll x) { return x * x; } bool connect(int a , int b) { if(squ(xn[a] - xm[b]) + squ(yn[a] - ym[b]) > squ(rn[a])) return 0; int i; for(i = 1 ; i <= k ; i ++ ) if(squ(xn[a] - xk[i]) + squ(yn[a] - yk[i]) <= squ(rk[i]) || squ(xm[b] - xk[i]) + squ(ym[b] - yk[i]) <= squ(rk[i]) || ( squ(yn[a] * (xk[i] - xm[b]) - ym[b] * (xk[i] - xn[a]) - yk[i] * (xn[a] - xm[b])) <= squ(rk[i]) * (squ(xn[a] - xm[b]) + squ(yn[a] - ym[b])) && squ(xn[a] - xm[b]) + squ(yn[a] - ym[b]) + squ(xn[a] - xk[i]) + squ(yn[a] - yk[i]) >= squ(xm[b] - xk[i]) + squ(ym[b] - yk[i]) && squ(xn[a] - xm[b]) + squ(yn[a] - ym[b]) + squ(xm[b] - xk[i]) + squ(ym[b] - yk[i]) >= squ(xn[a] - xk[i]) + squ(yn[a] - yk[i]))) return 0; return 1; } void add(int x , int y , int z) { to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt; to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt; } bool bfs() { int x , i; memset(dis , 0 , sizeof(dis)); while(!q.empty()) q.pop(); dis[s] = 1 , q.push(s); while(!q.empty()) { x = q.front() , q.pop(); for(i = head[x] ; i ; i = next[i]) { if(val[i] && !dis[to[i]]) { dis[to[i]] = dis[x] + 1; if(to[i] == t) return 1; q.push(to[i]); } } } return 0; } int dinic(int x , int low) { if(x == t) return low; int temp = low , i , k; for(i = head[x] ; i ; i = next[i]) { if(val[i] && dis[to[i]] == dis[x] + 1) { k = dinic(to[i] , min(temp , val[i])); if(!k) dis[to[i]] = 0; val[i] -= k , val[i ^ 1] += k; if(!(temp -= k)) break; } } return low - temp; } bool judge(int mid) { int i , j , sum = 0; memset(head , 0 , sizeof(head)) , cnt = 1; for(i = 1 ; i <= n ; i ++ ) add(s , i , mid / tn[i] + 1); for(i = 1 ; i <= m ; i ++ ) add(i + n , t , 1); for(i = 1 ; i <= n ; i ++ ) for(j = 1 ; j <= m ; j ++ ) if(v[i][j]) add(i , j + n , 1); while(bfs()) sum += dinic(s , 1 << 30); return sum == m; } int main() { int i , j , l = 0 , r = 2000000 , mid , ans = -1; scanf("%d%d%d" , &n , &m , &k) , s = 0 , t = n + m + 1; for(i = 1 ; i <= n ; i ++ ) scanf("%lld%lld%lld%lld" , &xn[i] , &yn[i] , &rn[i] , &tn[i]); for(i = 1 ; i <= m ; i ++ ) scanf("%lld%lld" , &xm[i] , &ym[i]); for(i = 1 ; i <= k ; i ++ ) scanf("%lld%lld%lld" , &xk[i] , &yk[i] , &rk[i]); for(i = 1 ; i <= n ; i ++ ) for(j = 1 ; j <= m ; j ++ ) v[i][j] = connect(i , j); while(l <= r) { mid = (l + r) >> 1; if(judge(mid)) ans = mid , r = mid - 1; else l = mid + 1; } printf("%d\n" , ans); return 0; }
相关文章
- RDD:基于内存的集群计算容错抽象
- Java实现 蓝桥杯VIP 算法训练 平方计算
- Java实现 蓝桥杯VIP 算法训练 薪水计算
- Serverless 解惑——函数计算如何访问 MySQL 数据库
- 数据分析的主要内容仍是结构化计算_数据分析师
- SPSS详细教程:OR值的计算
- BigDecimal代替浮点数精确计算用法简介
- 【云栖大会】阿里金融云总经理徐敏:金融云时代计算、连接与信任
- Image数据数值计算处理的一个小问题
- C/C++基础讲解(三十五)之数值计算与趣味数学篇(搬山游戏与兔子产子<菲波那契数列>)
- VXLAN配置实例(五)——云计算数据中心访问公司外部站点典型配置实例(超级超级难的网络配置!!!)
- Xcode 如何计算整个项目的代码行数
- Cloud Computing:云计算的简介之云计算的三层服务类型(从服务的层次)——IaaS、PaaS、SaaS的简介、核心技术之详细攻略
- 5G新型网络架构关键技术 — 控制能力重构、网络能力开放、按需组网、网络边缘缓存与计算
- 华为:与全球180万云与计算开发者共成长,共创行业新价值
- 【华为云技术分享】解密如何使用昇腾AI计算解决方案构建业务引擎
- m云计算任务调度优化matlab仿真,输出成本,时间,负荷优化结果,对比ACO,PSO,WOA三种优化算法
- m基于FPGA的PID控制器实现,包含testbench测试程序,PID整定通过matlab使用RBF网络计算
- python数据分析-numpy数值分析与计算操作
- 基于 ClickHouse OLAP 的生态:构建基于 ClickHouse 计算存储为核心的“批流一体”数仓体系...
- 华为云计算之虚拟化网络平面
- 大数据流式计算:关键技术及系统实例