【bzoj3035】【codevs2490】导弹防御塔 二分+匈牙利 || 二分+dinic
2016-03-02 11:20
423 查看
题目描述 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 1 0 0 0 50 50 0 50 50 0 1000 1000 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; }
相关文章推荐
- Cannot change version of project facet Dynamic Web Module to 3.0.
- CSS控制文本自动换行
- SDL2.0实现触控方法,让屏幕跟随你的手指动起来
- HTML学习笔记(一)block,inline和inline-block的概念和区别
- perl return和break
- 解决Android端升级安装后自动打开的问题
- 卷积神经网络(深度学习)一些问题总结
- statfs获得硬盘使用情况 模拟linux命令 df
- redis3.0.7连接 <java>
- 《Linux目录知识介绍》
- 0302思考
- 0302作业
- Bash Shell的使用环境
- 自然语言处理中训练集,开发集和测试集的关系
- java定时器
- python3 encode decode base64
- android的一些简单优化
- opencv 直方图calcHist
- ocm相关文章
- 将war包部署到android服务器上