zoukankan      html  css  js  c++  java
  • [9018_2101]保卫萝卜

    题目描述

    一群怪物正向着你的萝卜出发……

    这群怪物共有N只,第i只怪物的HP为Ai,当怪物的HP减少到0时,这个怪物就被摧毁了。现在你有M座防御塔,其中第i个防御塔每秒可以减少一只怪物Bi点的HP。由于怪物有不同的属性,所以某些怪物会对某些防御塔免疫。

    你的任务是计算至少需要多少时间才能消灭所有的怪物。

    输入

    第一行两个正整数N,M

    第二行N个正整数,表示A1~An

    第三行M个正整数,表示B1~Bn

    接下来是一个M*N的矩阵,矩阵中每个元素均为0或1。第i行第j列为1表示第i座防御塔可以攻击第j只怪物,为0表示第j只怪物对第i座防御塔的攻击免疫。

    输出

    一行,一个实数,表示所需的最小时间。保留3位小数

    样例输入

    2 2
    3 10
    4 6
    0 1
    1 1

    样例输出

    1.300

    提示

    前0.5s "Times New Roman"">,防御塔1攻击2号怪物,防御塔2 "Times New Roman"">攻击1号怪物。1号怪物被摧毁,2 "Times New Roman"">号怪物剩下8点HP。


    接下来0.8s "Times New Roman"">,1号和2号防御塔同时攻击2 "Times New Roman"">号怪物。2号怪物被摧毁。


    对于全部的数据,1<=N,M<=50 "Times New Roman"">,1<=Ai<=10^5 "Times New Roman"">,1<=Bi<=10^4 "Times New Roman"">,输入数据确保不存在同时对所有防御塔免疫的怪物

    二分答案+最大流check
    二分击杀所有怪物所用时间
    从源点s向每座塔连一条容量为t*b[i]的边,表示塔在t秒内的总输出
    从每座塔向不能免疫它的攻击的怪物连一条容量为INF的边,表示该塔可以攻击怪物
    从每个怪物向汇点连一条容量为怪物血量的边,表示该怪物能承受这么多的输出
    对于每个二分出来的t,检查是否满流
    若满流,表示怪物全部被击杀,可以减少时间,否则,表示有怪物还活着,需增加时间
    注意浮点误差
    #include<iostream> 
    #include<cstdio> 
    #include<cstring> 
    #include<cmath> 
    #define eps 1e-5 
    #define INF 999999999 
    using namespace std; 
    int h[1000],to[100000],nxt[100000],k=1,level[1000],iter[1000],s,t,n,m;double tot=0.0; 
    int H=0,T=0,que[100000],A[51],B[51];double ca[100000]; 
    bool mp[1000][1000]; 
    void ins(int u,int v,double cap) 
    { 
        nxt[++k]=h[u];to[k]=v;ca[k]=cap;h[u]=k; 
        nxt[++k]=h[v];to[k]=u;ca[k]=0;h[v]=k; 
    } 
    void bfs() 
    { 
        memset(level,0,sizeof(level)); 
        H=T=0;que[T++]=s;level[s]=1; 
        while(H!=T) 
        { 
            int u=que[H++]; 
            for(int i=h[u];i;i=nxt[i]) 
            { 
                if(!level[to[i]]&&abs(ca[i])>=eps) 
                { 
                    level[to[i]]=level[u]+1;que[T++]=to[i]; 
                } 
            } 
        } 
    } 
    double dfs(int u,double f) 
    { 
        if(u==t)return f; 
        double used=0,w; 
        for(int &i=iter[u];i;i=nxt[i]) 
        { 
            if(abs(ca[i])>=eps&&level[to[i]]==level[u]+1) 
            { 
                w=f-used;w=dfs(to[i],min(w,ca[i])); 
                if(abs(w)>=eps) 
                { 
                    ca[i]-=w;ca[i^1]+=w;used+=w;if(used==f)return f; 
                } 
            } 
        } 
        return used; 
    } 
    double dinic() 
    { 
        double flow=0; 
        for(;;) 
        { 
            for(int i=1;i<=n+m+2;i++)iter[i]=h[i]; 
            bfs();if(!level[t])return flow; 
            flow+=dfs(s,INF); 
        } 
        return flow; 
    } 
    double erfen(double L,double R) 
    { 
        while(R-L>eps) 
        { 
            double mid=(L+R)/2; 
            k=1;memset(h,0,sizeof(h)); 
            for(int i=1;i<=n;i++)ins(i+m,t,(double)A[i]); 
            for(int i=1;i<=m;i++)ins(s,i,(double)mid*B[i]); 
            for(int i=1;i<=m;i++) 
            for(int j=1;j<=n;j++)ins(i,j+m,(double)INF); 
            double ff=dinic(); 
            if(abs(ff-tot)<eps)R=mid; 
            else L=mid; 
        } 
        return L; 
    } 
    int main() 
    { 
        scanf("%d%d",&n,&m);s=n+m+1,t=n+m+2; 
        for(int i=1;i<=n;i++){scanf("%d",&A[i]);tot+=(double)A[i];} 
        for(int i=1;i<=m;i++)scanf("%d",&B[i]); 
        for(int i=1;i<=m;i++) 
        for(int j=1;j<=n;j++) 
        { 
            int q;scanf("%d",&q);mp[i][j]=1; 
        } 
        printf("%.3lf",erfen(0.0,5000000.0)); 
        return 0; 
    } 

     

  • 相关阅读:
    BZOJ1263: [SCOI2006]整数划分
    BZOJ2084: [Poi2010]Antisymmetry
    storage和memory
    快速理解区块链
    IPNS节点ID
    创建上传目录存储文件
    ipfs上传下载
    Solidity函数view,pure,constant的用法
    Truffle框架环境搭建
    以太坊常用钱包(测试币获取)
  • 原文地址:https://www.cnblogs.com/lher/p/7128057.html
Copyright © 2011-2022 走看看