Tyvj1935 导弹防御塔

真的是一道不错的题目诶

Description

link

\(Freda Shi\) 的城堡遭受了 \(M\) 个入侵者的攻击!

\(Freda\) 控制着 \(N\) 座导弹防御塔,每座塔都有足够数量的导弹,但是每次只能发射一枚。

每座塔每次发射前需要预热 \(T_1\) 秒,发射后需要冷却 \(T_2\) 秒。

给定塔和入侵者的坐标。

导弹从塔发出直到击中目标所需的飞行时间 \(=\) 塔和入侵者之间的距离 \(/\) 速度。

\(Freda\) 想用最少的时间击退所有的入侵者,请你告诉她一种攻击最小时间。

\(n,m \le 50\)

Solution

首先是道狗粮题

首先发现这个题不用考虑复杂度,随便做就行了

扫描二维码关注公众号,回复: 10483465 查看本文章

首先我们这个最值并不好做,那么转二分答案

二分时间 \(T\)\(T\) 是不是可行

\(check\) 函数里面做二分图完备匹配

预处理每一座塔和每个入侵者的距离

塔和入侵者是可以分列左右的,所以这玩意是个二分图

拆点:若某座塔在 \(T\) 秒内可以发射 \(X\) 次导弹,就把这座塔拆成 \(X\) 个点。

建边的条件:

导弹 \(A\)\(S\) 秒时发射,飞到入侵者 \(B\)\(V\) 秒,若 \(S+V \le T\),就连边

剩下的都是板子,正所谓:二分图网络流考得都是建图

一个比较神奇的事情:笔者自己并不知道为啥链式前向星会\(RE\),自闭后改 \(vector\) 就过了

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
	inline int read()
	{
		int res=0,f=1; char k;
		while(!isdigit(k=getchar())) if(k=='-') f=-1;
		while(isdigit(k)) res=res*10+k-'0',k=getchar();
		return res*f;
	}
	const int N=1010;
	vector<int> vec[N];
	double x[N],y[N],dis[N][N],t1,t2,v,p[N],q[N];
	int n,m,ans,to[N];
	inline void prework()
	{
		for(int i=0;i<=m+10;++i) vec[i].clear(); 
		memset(to,-1,sizeof(to)); ans=0;
		return ;
	}
	bool vis[N<<10];
	inline bool dfs(int x)
	{
		int sz=vec[x].size();
		for(int i=0;i<sz;++i)
		{
			int t=vec[x][i]; if(vis[t]) continue;
			vis[t]=1; if(to[t]==-1||dfs(to[t])) return to[t]=x,1; 
		}return 0;
	}
	inline bool check(double now)
	{
		prework(); 
		int k=1;
		while(now>=t1)
		{
			now-=t1; ++k;
			for(int i=1;i<=m;++i)
			{
				for(int j=1;j<=n;++j)
				{
					if(dis[j][i]<=now) vec[i].push_back(m+(k-1)*n+j); 
				}
			}now-=t2;
		}
		for(int i=1;i<=m;++i)
		{
			memset(vis,0,sizeof(vis));
			if(dfs(i)) ++ans;
		}
		return ans==m;
	}
	signed main()
	{
		n=read(); m=read(); scanf("%lf%lf%lf",&t1,&t2,&v); t1/=60;
		for(int i=1;i<=m;++i) scanf("%lf%lf",&x[i],&y[i]);
		for(int i=1;i<=n;++i) scanf("%lf%lf",&p[i],&q[i]);
		for(int i=1;i<=n;++i) 
		{
			for(int j=1;j<=m;++j)
			{
				dis[i][j]=sqrt((x[j]-p[i])*(x[j]-p[i])+(y[j]-q[i])*(y[j]-q[i]))/v;
			}
		}
		double l=t1,r=1e6+10;
		while(r-l>1e-8)
		{
			double mid=(l+r)/2;
			if(check(mid)) r=mid; 
			else l=mid;
		} printf("%.6lf\n",r);
		return 0;
	}
}
signed main(){return  yspm::main();} 

猜你喜欢

转载自www.cnblogs.com/yspm/p/12634320.html