您的位置:首页 > 其它

ZOJ3460 Missile(神奇的建图)

2016-02-14 15:07 253 查看
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3460

感叹出题人的脑洞。。。

这里把第i个基地第j次发射导弹这一事件记作点(j-1)*N+i,这样就成功处理了分次发射导弹的问题。。每个点都和目标相连,边权为所花的时间,即:j*T1+(j-1)*T2+d/V,然后二分时间限制。求二分匹配时如果对应边的权大于时间限制就不选此边,然后看最大匹配数是否等于m,若否则增大时间限;否则减小时间限。直到这一次与上一次的时间限小于1e-6,既达到目标精度。。

代码:

#include<cstdio>

#include<cstring>

#include<cmath>

#include<queue>

using namespace std;

#define N 55

#define M 2510

#define eps 1e-8

#define INF 200000000

#define min(x,y) ((x)<(y)?(x):(y))

#define max(x,y) ((x)>(y)?(x):(y))

#define d(x,y) sqrt((x)*(x)+(y)*(y))

double G
[M],limit,A
[2],B[M][2];

bool vis[M];

int Nx,Ny,Mx
,My[M],dx
,dy[M],dis;

bool bfs(){

    queue<int> q;dis=INF;int u;

    memset(dx,-1,sizeof(dx));

    memset(dy,-1,sizeof(dy));

    for(int i=1;i<=Nx;++i){

        if(Mx[i]==-1){q.push(i);dx[i]=0;}

    }

    while(!q.empty()){

        u=q.front();q.pop();

        if(dx[u]>dis) break;

        for(int i=1;i<=Ny;++i){

            if(G[u][i]<=limit&&dy[i]==-1){

                dy[i]=dx[u]+1;

                if(My[i]==-1) dis=dy[i];

                else{

                    dx[My[i]]=dy[i]+1;q.push(My[i]);

                }

            }

        }

    }

    return dis!=INF;

}

bool dfs(int u){

    for(int i=1;i<=Ny;++i){

        if(G[u][i]<=limit&&!vis[i]&&dy[i]==dx[u]+1){

            vis[i]=true;

            if(My[i]!=-1&&dy[i]==dis) continue;

            if(My[i]==-1||dfs(My[i])){

                My[i]=u;Mx[u]=i;return true;

            }

        }

    }

    return false;

}

int MaxMatch(){

    int ans=0;

    memset(Mx,-1,sizeof(Mx));

    memset(My,-1,sizeof(My));

    while(bfs()){

        memset(vis,false,sizeof(vis));

        for(int i=1;i<=Nx;++i){

            if(Mx[i]==-1&&dfs(i)) ++ans;

        }

    }

    return ans;

}

int main(){

    int n,m,ans;double L,R,T1,T2,v;

    while(scanf("%d%d%lf%lf%lf",&n,&m,&T1,&T2,&v)!=EOF){

        L=INF;R=-INF;Nx=m;Ny=n*m;T1=T1/60;

        for(int i=1;i<=m;++i) scanf("%lf%lf",&A[i][0],&A[i][1]);

        for(int i=1;i<=n;++i){

            scanf("%lf%lf",&B[i][0],&B[i][1]);

            for(int j=1;j<=m;++j){

                G[j][i]=d(A[j][0]-B[i][0],A[j][1]-B[i][1])/v+T1;

                L=min(L,G[j][i]);R=max(R,G[j][i]);

                for(int k=1;k<m;++k){

                    G[j][k*n+i]=G[j][i]+(T1+T2)*k;

                    L=min(L,G[j][k*n+i]);R=max(R,G[j][k*n+i]);

                }

            }

        }

        while(R-L>eps){

            limit=(L+R)/2;

            ans=MaxMatch();

            if(ans==m) R=limit;

            else L=limit;

        }

        printf("%.6lf\n",limit);

    }

    return 0;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息