【NOIP2013模拟】导弹防御塔

来源:互联网 发布:网络四十部色情禁书 编辑:程序博客网 时间:2024/05/21 09:05

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);}
1 0
原创粉丝点击