ZOJ3460 Missile 二分图拆点二分求解

来源:互联网 发布:小说素材软件 编辑:程序博客网 时间:2024/06/05 13:28

题目描述:

Description
You control N missile launching towers. Every tower has enough missiles, but for each tower only one missile can be launch at the same time. Before the launching, every missile need T1 seconds to leave the tower. Assume that all the missiles have the same speed V, and it would fly along the shortest path to the target. You can just consider the horizontal distance and ignore the height. You can consider the time equal to distance / V (minutes). The missile can immediately destroy the target when it reached. Besides, for the same tower, after launching a missile, it need T2 minutes to prepare for the next one.

Now, give you the coordinate position of N missile launching towers and M targets, T1, T2 and V, you should find the minimum minutes to destroy all the targets.

Input
The input will consist of about 10 cases. The first line of each case contains five positive integer numbers N, M, T1, T2 and V, decribed as above. The next M lines contains two integer numbers indicating the coordinate of M targets. The continueing N lines contains two integer numbers indicating the coordinate of N towers.
To all the cases, 1 ≤ N ≤ 50, 1 ≤ M ≤ 50
The absolute value of all the coordinates will not exceed 10000, T1, T2, V will not exceed 2000.

Output
For each case, the output is only one line containing only one real number with six digits precision (after a decimal point) indicating the minimum minutes to destroy all the targets.

Sample Input

3 3 30 20 10 00 5050 050 500 10001000 0

Sample Output

91.500000

题目分析:

有n个导弹,射向m个目标,每个导弹发射前有t1秒时间,在发射一个导弹后需要t2分,射向目标需要时间为:距离/v 分。问需要最少时间能把所有目标全都击中。
这题一看就是道二分图的题,因为导弹和目标这两方很明确,但是有一个问题就是这个建图。不能直接建,因为一个导弹发射点可以射出很多的导弹,所以我们要改变一下,将每个发射点的数次发射所需要的时间都记录下来。二分可能的时间,每一次二分对满足该时间下的发射情况建边,跑Hungary模板看是否能把所有m个目标全击中,若能,向下二分时间,不能向上。找出最小需要的时间就是答案。

代码如下:

#include <iostream>#include <stdlib.h>#include <stdio.h>#include <string.h>#include <math.h>const double eps = 1e-8;const int MAXN = 55;const int MAXM = 3000;using namespace std;struct node{    double x,y;}tower[MAXN],target[MAXN];double t1,t2,v;int n,m;double d[MAXN][MAXN];double dd[MAXM][MAXN];bool g[MAXM][MAXN];int linker[MAXM];bool used[MAXM];bool dfs(int u){    for(int v=0; v<m; v++)    {        if(g[u][v] && !used[v])        {            used[v]=1;            if (linker[v]==-1 || dfs(linker[v]))            {                linker[v]=u;                return 1;            }        }    }    return 0;}bool hungary(double mid){    int res=0;    memset(g,0,sizeof(g));    for(int i=0; i<n*m; i++)    {        for(int j=0; j<m; j++)        {            if(dd[i][j]<=mid)            {                g[i][j]=1;//满足条件的再连边            }        }    }    memset(linker,-1,sizeof(linker));    for(int u=0; u<n*m; u++)    {        memset(used,0,sizeof(used));        if (dfs(u)) res++;    }    //printf("%d\n",res);    if (res==m) return true;    return false;}double dis(struct node a,struct node b){    return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)));}int main(){    while(~scanf("%d%d%lf%lf%lf",&n,&m,&t1,&t2,&v))    {        t1/=60.0;        for(int i=0; i<m; i++) scanf("%lf%lf",&target[i].x,&target[i].y);        for(int i=0; i<n; i++) scanf("%lf%lf",&tower[i].x,&tower[i].y);        for(int i=0; i<n; i++)        {            for(int j=0; j<m; j++)            {                d[i][j]=dis(target[j],tower[i])/v;            }        }        for(int i=0; i<n; i++)//第i个发射塔        {            for(int j=0; j<m; j++)//第j个目标            {                for(int k=0; k<m; k++)//发射塔i的第k次发射                {                    dd[i*m+k][j]=k*t2+(k+1)*t1+d[i][j];                }            }        }//这里的处理是关键//        for(int i=0; i<n*m; i++)//        {//            for(int j=0; j<m; j++)//            printf("%.6lf ",dd[i][j]);//            printf("\n");//        }        double l=0,r=200000000,mid;//二分        while(r-l>=eps)        {            mid=(l+r)/2.0;            //printf("%.6lf\n",mid);            if (hungary(mid)) r=mid;            else l=mid;        }        printf("%.6lf\n",l);    }    return 0;}
0 0
原创粉丝点击