ZOJ3460 Missile 二分图拆点二分求解
2016-04-28 12:05
513 查看
题目描述:
DescriptionYou 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
题目分析:
有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; }
相关文章推荐
- (BOOL)synchronize立即更新磁盘内容
- 计算机网络(自顶向下方法)
- mysql--学生课程成绩表
- Java报文或者同步的数据有个别乱码情况的处理.
- 学习配置tomcat虚拟主机
- 颜色校正
- C# 利用HttpListener监听处理Http请求
- AsyncTask源码分析
- Mac环境下服务器搭建
- 代码重构 —— 区分代码和数据
- php防止sql注入
- ERP流程一 总体说明
- 《foreach循环示例》
- windows下安装解压缩mysql
- #Codeforces 343 [div2] D. Babaei and Birthday Cake 【线段树优先队列查询优化】
- [置顶] 嗨~大家好,欢迎大家来这逛逛
- Python迁移MySQL数据到MongoDB脚本
- 系统启动流程
- 我有一个梦想
- [转载]Python标准库:内置函数sum(iterable[, start])