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 1 0 0 0 50 50 0 50 50 0 1000 1000 0
Sample Output
91.500000
题意:m个目标,n个炮台,坐标都已知,每个炮台发射导弹都需要准备时间t2,导弹在炮筒里需要时间t1(只有这个数是秒!!!其他的时间是分钟!!!!),只计算导弹运动的水平水平时间,速度都是v。问至少多少时间把所有目标都干掉==
超级脑洞题~。~ 最最让我们束手无策的是t1,t2的处理,考虑到数据范围只有50*50,很有可能是把数据分开,既然要用到t1,t2,我们想到把n个炮台拆成n*m炮台,把t1,t2加到每个炮台里面,记录时间的二维数组值就是每个实际炮台第几次发射发射到哪个目标所需要的时间,二分最大值,跑二分图,匹配是m的成立。
这种查找方法到时很常见,但是,数组第二维不是n*m 开到60就够了!!!要不tle
#include <iostream>
#include <stdio.h>
#include <string.h>
#include<cmath>
#define inf 0x3f3f3f3f
using namespace std;
const int MAXN=3000;
int uN,vN;//u,v数目
int g[MAXN][MAXN];
int linker[MAXN];
bool used[MAXN];
bool dfs(int u)//从左边开始找增广路径
{
int v;
for(v=0;v<vN;v++)//这个顶点编号从0开始,若要从1开始需要修改
if(g[u][v]&&!used[v])
{
used[v]=true;
if(linker[v]==-1||dfs(linker[v]))
{//找增广路,反向
linker[v]=u;
return true;
}
}
return false;//这个不要忘了,经常忘记这句
}
int hungary()
{
int res=0;
int u;
memset(linker,-1,sizeof(linker));
for(u=0;u<uN;u++)
{
memset(used,0,sizeof(used));
if(dfs(u)) res++;
}
return res;
}
struct node
{
double x,y;
}num1[60],num2[60];
double Time[3000][60];
int n,m;
double t1,t2,v;
double dist[60][60];
int main()
{
// freopen("cin.txt","r",stdin);
//freopen("out.txt","w",stdout);
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",&num1[i].x,&num1[i].y);//这里之前笔误写成了num2
for(int i=0;i<n;i++)scanf("%lf%lf",&num2[i].x,&num2[i].y);
for(int i=0;i<n;i++)//tower
for(int j=0;j<m;j++)//target
{
dist[i][j]=sqrt((num1[j].x-num2[i].x)*(num1[j].x-num2[i].x)+(num1[j].y-num2[i].y)*(num1[j].y-num2[i].y))/v;
// printf("i=%d,j=%d,dist=%lf\n",i,j,dist[i][j]);这里之前i,j写反了
}
for(int i=0;i<m;i++)//time
{
for(int j=0;j<n;j++)//target
{
for(int k=0;k<m;k++)//tower
{
Time[m*j+i][k]=dist[j][k]+(i+1)*t1+i*t2;
// printf("i=%d,j=%d,k=%d,Time=%lf,dist=%lf\n",i,j,k,Time[m*j+i][k],dist[j][k]);
}
}
}
double l=0.0,r=200000000000.0,mid;
uN=n*m,vN=m;
while(r-l>1e-8)
{
mid=(l+r)/2.0;
memset(g,0,sizeof(g));
for(int i=0;i<m*n;i++)
for(int j=0;j<m;j++)
if(Time[i][j]<=mid) g[i][j]=1;
int tmp=hungary();
// printf("tmp=%d\n",tmp);
if(tmp==m) r=mid;
else l=mid;
// printf("l=%lf,mid=%lf,r=%lf\n",l,mid,r);
}
printf("%.6lf\n",r);
}
return 0;
}