真的是一道不错的题目诶
\(Freda Shi\) 的城堡遭受了 \(M\) 个入侵者的攻击!
\(Freda\) 控制着 \(N\) 座导弹防御塔,每座塔都有足够数量的导弹,但是每次只能发射一枚。
每座塔每次发射前需要预热 \(T_1\) 秒,发射后需要冷却 \(T_2\) 秒。
给定塔和入侵者的坐标。
导弹从塔发出直到击中目标所需的飞行时间 \(=\) 塔和入侵者之间的距离 \(/\) 速度。
\(Freda\) 想用最少的时间击退所有的入侵者,请你告诉她一种攻击最小时间。
\(n,m \le 50\)
首先是道狗粮题
首先发现这个题不用考虑复杂度,随便做就行了
首先我们这个最值并不好做,那么转二分答案
二分时间 \(T\) 看 \(T\) 是不是可行
在\(check\) 函数里面做二分图完备匹配
预处理每一座塔和每个入侵者的距离
塔和入侵者是可以分列左右的,所以这玩意是个二分图
拆点:若某座塔在 \(T\) 秒内可以发射 \(X\) 次导弹,就把这座塔拆成 \(X\) 个点。
建边的条件:
导弹 \(A\) 在 \(S\) 秒时发射,飞到入侵者 \(B\) 需 \(V\) 秒,若 \(S+V \le T\),就连边
剩下的都是板子,正所谓:二分图网络流考得都是建图
一个比较神奇的事情:笔者自己并不知道为啥链式前向星会\(RE\),自闭后改 \(vector\) 就过了
#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();}
原文:https://www.cnblogs.com/yspm/p/12634320.html