【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;}
0 0
原创粉丝点击