您的位置:首页 > 其它

【NOIP2013模拟】导弹防御塔

2016-03-19 13:38 501 查看

Description

Freda的城堡——

“Freda,城堡外发现了一些入侵者!”

“喵…刚刚探究完了城堡建设的方案数,我要歇一会儿嘛lala~”

“可是入侵者已经接近城堡了呀!”

“别担心,rainbow,你看呢,这是我刚设计的导弹防御系统的说~”

“喂…别卖萌啊……”

Freda控制着N座可以发射导弹的防御塔。每座塔都有足够数量的导弹,但是每座塔每次只能发射一枚。在发射导弹时,导弹需要T1秒才能从防御塔中射出,而在发射导弹后,发射这枚导弹的防御塔需要T2分钟来冷却。

所有导弹都有相同的匀速飞行速度V,并且会沿着距离最短的路径去打击目标。计算防御塔到目标的距离Distance时,你只需要计算水平距离,而忽略导弹飞行的高度。导弹在空中飞行的时间就是 (Distance/V) 分钟,导弹到达目标后可以立即将它击毁。

现在,给出N座导弹防御塔的坐标,M个入侵者的坐标,T1、T2和V,你需要求出至少要多少分钟才能击退所有的入侵者。

Solution

讲解一下

首先,多个炮塔的导弹是可以同时发的,那么这道题就水很多了。

首先,考虑有发炮时间和冷却时间,对一个炮塔可以瞄准多个目标,多个目标瞄准后时间是连续的,所以可以接连不断地发炮。

用什么

发现是有两组点,长得那么像二分图啊。但是是求最小的分钟数,最大最小,二分!

怎么做

其实这是一个很经典的模型,一个图,求在一个过程之后的最大最小值,二分后,在判断是否可行。

因为可以发多个导弹,所以一个炮塔可以连出m条边,表示发m个炮。然后在连边的时候判断,这条边用的时间是否满足限制,否则不连边。

这道题好坑

输入的是n,m

但是下面的是以m,n的顺序输入的。

死白的是。

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
const int maxn=500000;
const int maxx=500000;
int i,j,t,n,m,ans,v,k;
double l,r,mid,dis[maxx],o,t1,t2;
int first[maxx],next[maxx],last[maxx],num,fan[maxn],d[maxx];
int x[maxn],y[maxn],xx[maxn],yy[maxn],tot;
int chang[maxx];
void add(int x,int y,double z){
last[++num]=y;
next[num]=first[x];
first[x]=num;
chang[num]=z;
fan[num]=num+1;
last[++num]=x;
next[num]=first[y];
first[y]=num;
chang[num]=0;
fan[num]=num-1;
}
double dian(int x,int y,int xx,int yy){
return sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
}
bool bfs(){
int i,j,k;
i=0;j=1;memset(dis,0,sizeof(dis));dis[0]=1;d[1]=0;
while(i<j){
k=first[d[++i]];
while(k!=0){
if(dis[last[k]]==0&&chang[k]>0){
dis[last[k]]=dis[d[i]]+1;
d[++j]=last[k];
}
k=next[k];
}
}
return (dis[n*m+m+1]!=0);
}
int dinic(int x,int y){
int i,j,t,p;
if (x==n*m+m+1){
return y;
}
j=first[x];
p=0;
while(j!=0){
i=last[j];
if (chang[j]>0&&dis[i]==dis[x]+1){
t=dinic(i,min(y,chang[j]));
if (t>0) {
chang[j]-=t;
chang[fan[j]]+=t;
y-=t;p+=t;if (y==0) break;
}

}
j=next[j];
}
if (p==0) dis[x]=-1;
return p;
}
bool pan(int x){
int t=0;
ans=0;
while(bfs()){
t=dinic(0,0x7fffffff);
ans+=t;
}
if(ans==m)return 1;else return 0;
}
int main(){
scanf("%d%d%lf%lf%d",&n,&m,&t1,&t2,&v);
fo(i,1,m){
scanf("%d%d",&x[i],&y[i]);
}
fo(i,1,n){
scanf("%d%d",&xx[i],&yy[i]);
}
l=0,r=100000;
while(r-l>1e-7){
mid=(l+r)/2;
memset(first,0,sizeof(first));
num=0;
fo(i,1,n) fo(j,1,m) add(0,(i-1)*m+j,1);
fo(i,1,n){
fo(j,1,m){
fo(k,1,m){
o=dian(xx[i],yy[i],x[k],y[k])/v+t1*j/60+t2*(j-1);
if(o>mid)continue;
add((i-1)*m+j,n*m+k,1);
}
}
}
fo(i,1,m)add(n*m+i,n*m+m+1,1);
if(pan(mid))r=mid;else l=mid;
}
printf("%.6lf\n",l);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: