6803 导弹防御塔 0x60「图论」例题
背景
Freda的城堡——
“Freda,城堡外发现了一些入侵者!”
“喵...刚刚探究完了城堡建设的方案数,我要歇一会儿嘛lala~”
“可是入侵者已经接近城堡了呀!”
“别担心,rainbow,你看呢,这是我刚设计的导弹防御系统的说~”
“喂...别卖萌啊……”
描述
Freda的城堡遭受了M个入侵者的攻击!Freda控制着N座导弹防御塔,每座塔都有足够数量的导弹,但是每次只能发射一枚。在发射导弹时,导弹需要 T_1 秒才能从防御塔中射出,而在发射导弹后,发射这枚导弹的防御塔需要 T_2 分钟来冷却。
所有导弹都有相同的匀速飞行速度V,并且会沿着距离最短的路径去打击目标。计算防御塔到目标的距离Distance时,你只需要计算水平距离,而忽略导弹飞行的高度。导弹在空中飞行的时间就是 (Distance/V) 分钟,导弹到达目标后可以立即将它击毁。
现在,给出N座导弹防御塔的坐标,M个入侵者的坐标,T_1,T_2 和V。因为Freda的小伙伴Rainbow就要来拜访城堡了,你需要求出至少多少分钟才能击退所有的入侵者。
输入格式
第一行五个正整数N,M,T1,T2,V。
接下来M行每行两个整数,代表入侵者的坐标。
接下来N行每行两个整数,代表防御塔的坐标。
输出格式
输出一个实数,表示最少需要多少分钟才能击中所有的入侵者,四舍五入保留六位小数。
样例输入
3 3 30 20 1 0 0 0 50 50 0 50 50 0 1000 1000 0
样例输出
91.500000
数据范围与约定
- 对于40%的数据,N,M<=20.
对于100%的数据, 1≤N≤50, 1≤M≤50,坐标绝对值不超过10000,T1,T2,V不超过2000.
题解
答案满足单调性,可以二分答案,转化为判定问题。
显然满足0要素和1要素。将导弹塔拆点,连边跑二分图匹配即可。注意这不是多重匹配,因为同一个导弹塔发射出的导弹不等价。
时间复杂度\(O(m*m*nm\log v)\)
#include<bits/stdc++.h> #define rg register #define il inline #define co const template<class T>il T read(){ rg T data=0,w=1;rg char ch=getchar(); for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w; for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0'; return data*w; } template<class T>il T read(rg T&x) {return x=read<T>();} typedef long long ll; using namespace std; typedef pair<int,int> pii; #define x first #define y second co int N=51,M=2501; co double eps=1e-8; int n,m,t,t2,V,f[M]; double t1; bool v[M]; pii a[N],b[N]; pair<int,double> c[M]; vector<int> e[N]; il double dis(co pii&a,co pii&b){ return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2)); } bool dfs(int x){ for(unsigned i=0;i<e[x].size();++i){ int y=e[x][i]; if(v[y]) continue; v[y]=1; if(!f[y]||dfs(f[y])){ f[y]=x; return 1; } } return 0; } bool judge(double mid){ memset(f,0,sizeof f); for(int i=1;i<=m;++i){ e[i].clear(); for(int j=1;j<=t;++j) if(c[j].y+dis(a[i],b[c[j].x])/V<=mid) e[i].push_back(j); } for(int i=1;i<=m;++i){ memset(v,0,sizeof v); if(!dfs(i)) return 0; } return 1; } int main(){ read(n),read(m),read(t1),read(t2),read(V); t=n*m,t1/=60; for(int i=1;i<=m;++i) read(a[i].x),read(a[i].y); for(int i=1;i<=n;++i) read(b[i].x),read(b[i].y); for(int i=1;i<=m;++i)for(int j=1;j<=n;++j){ int k=(i-1)*n+j; c[k].x=j,c[k].y=(i-1)*(t1+t2)+t1; } double l=t1,r=1e5; while(l+eps<r){ double mid=(l+r)/2; if(judge(mid)) r=mid; else l=mid; } printf("%.6lf\n",l); return 0; }
来源:https://www.cnblogs.com/autoint/p/10971508.html