• AC日记——[SDOI2015]星际战争 洛谷 P3324


    题目描述

    3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战。

    在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai。当一个巨型机器人的装甲值减少到0或者以下时,这个巨型机器人就被摧毁了。

    X军团有M个激光武器,其中第i个激光武器每秒可以削减一个巨型机器人Bi的装甲值。激光武器的攻击是连续的。

    这种激光武器非常奇怪,一个激光武器只能攻击一些特定的敌人。Y军团看到自己的巨型机器人被X军团一个一个消灭,他们急需下达更多的指令。

    为了这个目标,Y军团需要知道X军团最少需要用多长时间才能将Y军团的所有巨型机器人摧毁。但是他们不会计算这个问题,因此向你求助。

    输入输出格式

    输入格式:

    第一行,两个整数,N、M。第二行,N个整数,A1、A2...AN。第三行,M个整数,B1、B2...BM。接下来的M行,每行N个整数,这些整数均为0或者1。这部分中的第i行的第j个整数为0表示第i个激光武器不可以攻击第j个巨型机器人,为1表示第i个激光武器可以攻击第j个巨型机器人。

    输出格式:

    一行,一个实数,表示X军团要摧毁Y军团的所有巨型机器人最少需要的时间。输出结果与标准答案的绝对误差不超过10-3即视为正确。

    输入输出样例

    输入样例#1:
    2 2
    3 10
    4 6
    0 1
    1 1
    输出样例#1:
    1.300000

    说明

    【样例说明1】

    战斗开始后的前0.5秒,激光武器1攻击2号巨型机器人,激光武器2攻击1号巨型机器人。1号巨型机器人被完全摧毁,2号巨型机器人还剩余8的装甲值;

    接下来的0.8秒,激光武器1、2同时攻击2号巨型机器人。2号巨型机器人被完全摧毁。

    对于全部的数据,1<=N, M<=50,1<=Ai<=105,1<=Bi<=1000,输入数据保证X军团一定能摧毁Y军团的所有巨型机器人

    [spj]

    思路:

      二分+最大流;

      轻松ac;

      二分时间,用最大流判断是否能达到装甲总值;

    来,上代码:

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    #define maxn 101
    #define INF 9999999.99
    #define EFlit 10000.0
    
    using namespace std;
    
    struct EdgeType {
        int v,e;
        
        double f;
    };
    struct EdgeType edge[maxn*maxn<<1];
    
    int if_z,n,m,head[maxn<<2],s,t=(maxn<<2)-1;
    int ai[maxn],bi[maxn],tota,totb,map[maxn][maxn];
    int deep[maxn<<2],cnt;
    
    double dai[maxn],dbi[maxn];
    
    char Cget;
    
    inline void in(int &now)
    {
        now=0,if_z=1,Cget=getchar();
        while(Cget>'9'||Cget<'0')
        {
            if(Cget=='-') if_z=-1;
            Cget=getchar();
        }
        while(Cget>='0'&&Cget<='9')
        {
            now=now*10+Cget-'0';
            Cget=getchar();
        }
        now*=if_z;
        return ;
    }
    
    bool bfs()
    {
        queue<int>que;
        memset(deep,-1,sizeof(deep));
        que.push(s);deep[s]=0;
        while(!que.empty())
        {
            int pos=que.front();que.pop();
            for(int i=head[pos];i;i=edge[i].e)
            {
                if(deep[edge[i].v]<0&&edge[i].f>0)
                {
                    deep[edge[i].v]=deep[pos]+1;
                    if(edge[i].v==t) return true;
                    que.push(edge[i].v);
                }
            }
        }
        return false;
    }
    
    double flowing(int now,double flow)
    {
        if(now==t||flow==0) return flow;
        double oldflow=0;
        for(int i=head[now];i;i=edge[i].e)
        {
            if(deep[edge[i].v]==deep[now]+1&&edge[i].f>0)
            {
                double pos=flowing(edge[i].v,min(flow,edge[i].f));
                if(pos>0)
                {
                    flow-=pos;
                    oldflow+=pos;
                    edge[i].f-=pos;
                    edge[i^1].f+=pos;
                    if(flow==0) return oldflow;
                }
            }
        }
        if(oldflow==0) deep[now]=-1;
        return oldflow;
    }
    
    inline void edge_add(int u,int v,double f)
    {
        edge[++cnt].v=v,edge[cnt].f=f,edge[cnt].e=head[u],head[u]=cnt;
        edge[++cnt].v=u,edge[cnt].f=0,edge[cnt].e=head[v],head[v]=cnt;
    }
    
    bool check(double ans_)
    {
        cnt=1;
        memset(head,0,sizeof(head));
        for(int i=1;i<=m;i++) edge_add(s,i,dbi[i]*ans_);
        for(int i=1;i<=n;i++) edge_add(i+m,t,dai[i]);
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(map[i][j]) edge_add(i,j+m,INF);
            }
        }
        double pos=0;
        while(bfs()) pos+=flowing(s,INF);
        if(pos>=(double)tota-0.001) return true;
        else return false;
    }
    
    int main()
    {
        in(n),in(m);
        for(int i=1;i<=n;i++)
        {
            in(ai[i]);
            tota+=ai[i];
            dai[i]=ai[i];
        }
        for(int i=1;i<=m;i++)
        {
            in(bi[i]);
            totb+=bi[i];
            dbi[i]=bi[i];
        }
        for(int i=1;i<=m;i++)
        {
            for(int j=1;j<=n;j++) in(map[i][j]);
        }
        double l=(double)tota/(double)totb,r=EFlit,mid,ans;
    //    double l=0,r=EFlit,mid,ans;
        while(l<r)
        {
            mid=(l+r)/2.0;
            if(check(mid)) ans=mid,r=mid-0.0001;
            else l=mid+0.0001;
        }
        printf("%lf
    ",ans);
        return 0;
    }
  • 相关阅读:
    【基础】Attribute的妙用
    【翻译】.Net Core的意义
    【基础】迭代器详解
    【总结】数据库索引的实现原理
    【实践】基于接口的插件机制
    【总结】设计模式应用之单例模式
    【基础】多线程更新窗体UI的若干方法
    【基础】MVC路由规则
    Mybatis 分页:Pagehelper + 拦截器实现
    这四种对象属性拷贝方式,你都知道吗?
  • 原文地址:https://www.cnblogs.com/IUUUUUUUskyyy/p/6637919.html
Copyright © 2020-2023  润新知