• 【20170706】保卫萝卜


    题目描述

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

    这群怪物共有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位小数

    1.二分答案

    2.网络流check:S向每个塔连时间乘b[i]的边,塔向能够伤害的怪物连INF的边,怪物向T连a[i]的边,跑一遍最大流,看是否等于所有a[i]的总和;

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define INF 0x7fffffff
    #define MN 50
    #define T 101
    #define S 0
    #define eps 1e-5
    using namespace std;
    int n,m;
    double a[MN+5],b[MN+5],sum=0;
    bool ifcan[MN+5][MN+5];
    int cnt,top;
    int head[T+5],d[T+5],q[T*3+5];
    struct edge{int t,nex;double w;}e[MN*MN*2+MN*5];
    void ins(int f,int t,double w){
        e[++cnt].t=t; e[cnt].nex=head[f]; e[cnt].w=w; head[f]=cnt;
        e[++cnt].t=f; e[cnt].nex=head[t]; e[cnt].w=0; head[t]=cnt;
    }
    double dfs(int x,double f){
        if(x==T) return f;
        double used=0;
        for(int i=head[x];i;i=e[i].nex)
            if(e[i].w&&d[e[i].t]==d[x]+1){
                double w=dfs(e[i].t,min(f-used,e[i].w));
                used+=w;e[i].w-=w;e[i^1].w+=w;
                if(abs(f-used)<eps) return f;    
            }
        return d[x]=-1,used;
    }
    bool bfs(){
        memset(d,0,sizeof(d));int i,j;
        for(d[q[top=i=1]=S]=1;i<=top;++i){
            for(int j=head[q[i]];j;j=e[j].nex)
                if(e[j].w&&!d[e[j].t])
                    d[q[++top]=e[j].t]=d[q[i]]+1;
        }
        return d[T];
    }
    bool solve(double t){
        cnt=1;
        double ans=0.0;
        memset(head,0,sizeof(head));
        for(int i=1;i<=T;i++) head[i]=0;
        for(int i=1;i<=m;i++) ins(S,i,b[i]*t);
        for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) if(ifcan[i][j]) ins(i,j+50,INF);
        for(int i=1;i<=n;i++) ins(i+50,T,a[i]);
        while(bfs()) ans+=dfs(S,INF);
        if(abs(ans-sum)<eps) return 1;
        return 0;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%lf",&a[i]),sum+=a[i];
        for(int i=1;i<=m;i++) scanf("%lf",&b[i]);
        for(int i=1;i<=m;i++) for(int j=1;j<=n;j++) cin>>ifcan[i][j];
        double l=0.0,r=5000000.0;
        while(l+eps<r){
            double mid=(l+r)/2;
            if(solve(mid)) r=mid;
            else l=mid;
        }
        printf("%.3lf",l);
        return 0;
    } 

    ————————————————————————————————————

    来自Paper Cloud的博客,未经允许,请勿转载,谢谢。

  • 相关阅读:
    C语言程序设计第一次作业
    C语言I博客作业09
    C语言I博客作业08
    C语言I博客作业07
    C语言I博客作业06
    C语言I博客作业05
    C语言II博客作业03
    C语言II博客作业02
    C语言II博客作业01
    学期总结
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/7128886.html
Copyright © 2020-2023  润新知