【bzoj3035】【codevs2490】导弹防御塔 二分+匈牙利 || 二分+dinic
来源:互联网 发布:react.js .百度百科 编辑:程序博客网 时间:2024/05/17 22:11
题目描述 Description
Freda的城堡——
“Freda,城堡外发现了一些入侵者!”
“喵…刚刚探究完了城堡建设的方案数,我要歇一会儿嘛lala~”
“可是入侵者已经接近城堡了呀!”
“别担心,rainbow,你看呢,这是我刚设计的导弹防御系统的说~”
“喂…别卖萌啊……”
Freda控制着N座可以发射导弹的防御塔。每座塔都有足够数量的导弹,但是每座塔每次只能发射一枚。在发射导弹时,导弹需要T1秒才能从防御塔中射出,而在发射导弹后,发射这枚导弹的防御塔需要T2分钟来冷却。
所有导弹都有相同的匀速飞行速度V,并且会沿着距离最短的路径去打击目标。计算防御塔到目标的距离Distance时,你只需要计算水平距离,而忽略导弹飞行的高度。导弹在空中飞行的时间就是 (Distance/V) 分钟,导弹到达目标后可以立即将它击毁。
现在,给出N座导弹防御塔的坐标,M个入侵者的坐标,T1、T2和V,你需要求出至少要多少分钟才能击退所有的入侵者。
输入描述 Input Description
第一行五个正整数N,M,T1,T2,V。
接下来M行每行两个整数,代表入侵者的坐标。
接下来N行每行两个整数,代表防御塔的坐标。
输出描述 Output Description
输出一个实数,表示最少需要多少分钟才能击中所有的入侵者,四舍五入保留六位小数。
样例输入 Sample Input
3 3 30 20 10 00 5050 050 500 10001000 0
样例输出 Sample Output
91.500000
数据范围及提示 Data Size & Hint
对于40%的数据,N,M<=20.
对于100%的数据, 1≤N≤50, 1≤M≤50,坐标绝对值不超过10000,T1,T2,V不超过2000.
来源:Nescafe 19
Orzlyd
CH挂了,tyvj评测机评的和我手测不一样,幸亏codevs有…bzoj的还是T所以我敲个dinic去看看…
不好求极值,转为二分。
二分答案T,看看T个时间内能发多少个导弹,能发多少个就拆成多少个点,然后若某个导弹a时刻发出去,需要b时刻才能打中目标,那么这个点和目标连一条边,然后跑个匈牙利看看是不是完全匹配即可
还有就是论认真读题的重要性…题目中t1的单位是秒,t2和答案的单位是分钟…坑爹啊我半天没看见
……卡常数……卡二分上界……我不想说什么了……
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>using namespace std;const double INF = 30000;const int SZ = 1000010;int n,m;double t1,t2;double t[233][233];int head[SZ],nxt[SZ],tot = 0,to[SZ];void build(int f,int t){ to[++ tot] = t; nxt[tot] = head[f]; head[f] = tot;}bool vis[SZ];int match[SZ];bool dfs(int u){ for(int i = head[u];i;i = nxt[i]) { int v = to[i]; if(!vis[v]) { vis[v] = 1; if(!match[v] || dfs(match[v])) { match[v] = u; return true; } } } return false;}void init(){ tot = 0; memset(head,0,sizeof(head)); memset(to,0,sizeof(to)); memset(nxt,0,sizeof(nxt)); memset(match,0,sizeof(match));}double maxt = 0;bool check(double T){ init(); int d = (T - t1) / (t1 + t2) + 1; for(int i = 1;i <= n;i ++) { for(int j = 0;j < d;j ++) { double now = t1 + j * (t1 + t2); for(int k = 1;k <= m;k ++) { if(now + t[i][k] <= T) { build(i + j * n,d * n + k); build(d * n + k,i + j * n); } } } } int ans = 0; for(int i = 1;i <= d * n + m;i ++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans ++; }// printf("%d\n",ans); return ans / 2 == m;}double div(){ double l = t1,r = INF; for(int i = 1;i <= 40;i ++) { double mid = (l + r) / 2; if(check(mid)) r = mid; else l = mid; } return r;}int x[SZ],y[SZ];double calc(int x1,int y1,int x2,int y2){ double a = x1 - x2; double b = y1 - y2; return sqrt(a * a + b * b);}int main(){ double v; scanf("%d%d%lf%lf%lf",&n,&m,&t1,&t2,&v); t1 /= 60; for(int i = 1;i <= m;i ++) { scanf("%d%d",&x[i],&y[i]); } for(int i = 1;i <= n;i ++) { int xx,yy; scanf("%d%d",&xx,&yy); for(int j = 1;j <= m;j ++) { t[i][j] = calc(x[j],y[j],xx,yy) / v; } }/* for(int i = 1;i <= n;i ++) { for(int j = 1;j <= m;j ++) printf("%lf ",t[i][j]); puts(""); } */// check(91.5); printf("%.6lf\n",div()); return 0;}
bzoj的数据好像比较强…匈牙利过不了……
然后敲了个网络流还是过不了…
认真规划了一下数组大小和memset次数,可算过了…这方面从来没在意过的我QAQ
#include<cstdio>#include<cstring>#include<algorithm>#include<iostream>#include<cmath>#include<queue>using namespace std;const double INF = 30000;const int SZ = 500010;int n,m;double t1,t2;double t[233][233];int head[SZ],nxt[SZ],tot = 1,s,e;struct edge{ int t,d;}l[SZ];void build(int f,int t,int d){ l[++ tot].t = t; l[tot].d = d; nxt[tot] = head[f]; head[f] = tot;}void insert(int f,int t,int d){ build(f,t,d); build(t,f,0);}queue<int> q;int deep[SZ];bool bfs(){ memset(deep,0,sizeof(deep)); while(q.size()) q.pop(); deep[s] = 1; q.push(s); while(q.size()) { int f = q.front(); q.pop(); for(int i = head[f];i;i = nxt[i]) { int v = l[i].t; if(!deep[v] && l[i].d) { deep[v] = deep[f] + 1,q.push(v); // if(v == e) return true; } } } if(deep[e]) return true; return false;}int dfs(int u,int flow){ if(u == e || flow == 0) return flow; int rest = flow; for(int i = head[u];i;i = nxt[i]) { int v = l[i].t; if(deep[v] == deep[u] + 1 && l[i].d) { int f = dfs(v,min(rest,l[i].d)); if(f > 0) { rest -= f; l[i].d -= f; l[i ^ 1].d += f; if(!rest) break; } else deep[v] = 0; } } if(flow - rest == 0) deep[u] = 0; return flow - rest;}int dinic(){ int ans = 0; while(bfs()) { int tmp = dfs(s,INF); if(tmp == 0) break; ans += tmp; } return ans;}void init(){ tot = 1; memset(head,0,sizeof(head));}bool check(double T){ init(); int d = (T - t1) / (t1 + t2) + 1; for(int i = 1;i <= n;i ++) { for(int j = 0;j < d;j ++) { double now = t1 + j * (t1 + t2); for(int k = 1;k <= m;k ++) { if(now + t[i][k] <= T) { insert(i + j * n,d * n + k,1); } } } } s = 0; e = d * n + m + 1; for(int i = 1;i <= d * n;i ++) insert(s,i,1); for(int i = d * n + 1;i <= d * n + m;i ++) insert(i,e,1); return dinic() == m;}double div(){ double l = t1,r = INF; for(int i = 1;i <= 40;i ++) { double mid = (l + r) / 2; if(check(mid)) r = mid; else l = mid; } return r;}int x[SZ],y[SZ];double calc(int x1,int y1,int x2,int y2){ double a = x1 - x2; double b = y1 - y2; return sqrt(a * a + b * b);}int main(){ double v; scanf("%d%d%lf%lf%lf",&n,&m,&t1,&t2,&v); t1 /= 60; for(int i = 1;i <= m;i ++) { scanf("%d%d",&x[i],&y[i]); } for(int i = 1;i <= n;i ++) { int xx,yy; scanf("%d%d",&xx,&yy); for(int j = 1;j <= m;j ++) { t[i][j] = calc(x[j],y[j],xx,yy) / v; } } printf("%.6lf\n",div()); return 0;}
- 【bzoj3035】【codevs2490】导弹防御塔 二分+匈牙利 || 二分+dinic
- CodeVS2490 导弹防御塔 【二分答案】【匈牙利】
- 二分图最大匹配模板【匈牙利;Dinic最大流】
- [二分图]导弹拦截
- POJ 2112 二分+dinic
- 1669 DINIC+二分
- nyoj 310二分+dinic
- poj2391 二分+floyd+dinic
- poj2112 二分+floyd+dinic
- 【codevs1422】河城荷取 二分+dinic
- POJ 3189 二分+Dinic
- nyoj-239 月老的难题 (二分图匹配—匈牙利算法 && 网络流—Dinic算法)
- 二分图匈牙利算法
- 二分匹配 ---- 匈牙利算法
- 二分图匈牙利算法
- 二分图 匈牙利算法
- 匈牙利算法 二分图
- 二分图 匈牙利算法
- perl return和break
- PDF格式文件的基本编辑操作
- Nginx 隐藏服务器名称和版本号
- Cannot change version of project facet Dynamic Web Module to 3.0.
- 解决Android端升级安装后自动打开的问题
- 【bzoj3035】【codevs2490】导弹防御塔 二分+匈牙利 || 二分+dinic
- 《Linux目录知识介绍》
- Provider使用遇到错误
- WEB开发框架配置文件和各层注解(SpringMVC + Spring + Hibernate)
- 关于正规方程求解线性回规问题中的最终的值θ
- UNITY3D shader学习心得<三> Vertex and Fragment Shader
- 加载js 简单获取get传递参数
- 二叉树递归遍历中的return
- iOS开发之JS数据交互