• 【BZOJ3993】星际战争(网络流,二分答案)


    【BZOJ3993】星际战争(网络流,二分答案)

    题面

    Description

    3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战。在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai。当一个巨型机器人的装甲值减少到0或者以下时,这个巨型机器人就被摧毁了。X军团有M个激光武器,其中第i个激光武器每秒可以削减一个巨型机器人Bi的装甲值。激光武器的攻击是连续的。这种激光武器非常奇怪,一个激光武器只能攻击一些特定的敌人。Y军团看到自己的巨型机器人被X军团一个一个消灭,他们急需下达更多的指令。为了这个目标,Y军团需要知道X军团最少需要用多长时间才能将Y军团的所有巨型机器人摧毁。但是他们不会计算这个问题,因此向你求助。

    Input

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

    Output

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

    Sample Input

    2 2

    3 10

    4 6

    0 1

    1 1

    Sample Output

    1.300000

    HINT

    【样例说明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军团的所有巨型机器人

    题解

    每个激光武器造成的伤害是一定的
    只是分配的问题
    于是,在固定的时间里,产生的总伤害是一定的
    因此,二分一个时间
    检查在这个时间内产生的伤害是否等于机器人的总血量即可

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<set>
    #include<map>
    #include<vector>
    #include<queue>
    using namespace std;
    #define INF 1e9
    #define MAXL 50000
    #define MAX 500
    inline int read()
    {
    	int x=0,t=1;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=-1,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return x*t;
    }
    int A[MAX],B[MAX];
    int g[MAX][MAX];
    struct Line
    {
        int v,next;
    	double w;
    }e[MAXL];
    int h[MAX],cnt;
    int ans,S,T,n,m;
    inline void Add(int u,int v,double w)
    {
        e[cnt]=(Line){v,h[u],w};
        h[u]=cnt++;
        e[cnt]=(Line){u,h[v],0};
        h[v]=cnt++;
    }
    int level[MAX];
    int cur[MAX];
    bool BFS()
    {
        memset(level,0,sizeof(level));
        level[S]=1;
        queue<int> Q;
        Q.push(S);
        while(!Q.empty())
        {
            int u=Q.front();Q.pop();
            for(int i=h[u];i!=-1;i=e[i].next)
            {
                int v=e[i].v;
                if(e[i].w&&!level[v])
                    level[v]=level[u]+1,Q.push(v);
            }
        }
        return level[T];
    }
    double DFS(int u,double flow)
    {
        if(flow==0||u==T)return flow;
        double ret=0;
        for(int &i=cur[u];i!=-1;i=e[i].next)
        {
            int v=e[i].v;
            if(e[i].w&&level[v]==level[u]+1)
            {
                double dd=DFS(v,min(flow,e[i].w));
                flow-=dd;ret+=dd;
                e[i].w-=dd;e[i^1].w+=dd;
            }
        }
        return ret;
    }
    double Dinic()
    {
        double ret=0;
        while(BFS())
        {
            for(int i=S;i<=T;++i)cur[i]=h[i];
            ret+=DFS(S,INF);
        }
        return ret;
    }
    void Build(double tt)
    {
    	memset(h,-1,sizeof(h));
    	cnt=0;
    	for(int i=1;i<=m;++i)Add(S,i,tt*B[i]);
    	for(int i=1;i<=n;++i)Add(i+m,T,A[i]);
    	for(int i=1;i<=m;++i)
    		for(int j=1;j<=n;++j)
    			if(g[i][j])
    				Add(i,j+m,1e9);
    }
    int main()
    {
    	n=read();m=read();
    	S=0;T=n+m+1;
    	double sum=0;
    	for(int i=1;i<=n;++i)sum+=A[i]=read();
    	for(int i=1;i<=m;++i)B[i]=read();
    	for(int i=1;i<=m;++i)
    		for(int j=1;j<=n;++j)
    			g[i][j]=read();
    	double l=0,r=1e6;
    	while(r-l>1e-5)
    	{
    		double mid=(l+r)/2;
    		Build(mid);
    		if(Dinic()>=sum)r=mid;
    		else l=mid;
    	}
    	printf("%.6lf
    ",l);
    	return 0;
    }
    
    
  • 相关阅读:
    04_web基础(六)之请求转发与重定向
    04_web基础(五)之cookie与session
    04_web基础(四)之servlet详解
    04_web基础(三)之进一步理解web
    04_web基础(二)之web构建
    本地密码提取工具-LAZAGNE
    免杀工具汇总
    流量取证-提取文件
    CA证书安装以及sslh协议转发
    ssh 端口转发
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8136737.html
Copyright © 2020-2023  润新知