CH6803 导弹防御塔

背景

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.
        </article>

题解

答案满足单调性,可以二分答案,转化为判定问题。

显然满足0要素和1要素。将导弹塔拆点,连边跑二分图匹配即可。注意这不是多重匹配,因为同一个导弹塔发射出的导弹不等价。

时间复杂度(O(m*m*nmlog 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
",l);
	return 0;
}
原文地址:https://www.cnblogs.com/autoint/p/10971508.html