zoukankan      html  css  js  c++  java
  • BZOJ3993: [SDOI2015]星际战争

    BZOJ3993: [SDOI2015]星际战争

    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军团的所有巨型机器人

    题解Here!
    很容易想到我们二分所需要的时间$T$。
    然后用网络流判定是否能在这段时间内打完。
    建图很简单:

    从$S$到每一个武器$i$连一条边,容量为$B_i imes t$。

    从每一个机器人$i+m$向$T$连一条边,容量为$A_i$。

    从每个武器向所有能攻击的机器人连一条边,容量为$MAX$。

    然后就可以跑了。

    对于精度问题,注意到这题的精度要求并不是很高。

    可以不用$double$二分及计算,把所有的流量全部乘以$10000$即可。

    记得开$long long$。

    附代码:

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<queue>
    #include<cstring>
    #define MAXN 60
    #define MAX (1LL<<62)
    using namespace std;
    int n,m,c=2,s,t;
    long long sum=0,blood[MAXN],attack[MAXN];
    bool edge[MAXN][MAXN];
    int head[MAXN<<1],deep[MAXN<<1];
    struct node{
    	int next,to;
    	long long w;
    }a[MAXN*MAXN<<1];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline void add(int u,int v,long long w){
    	a[c].to=v;a[c].w=w;a[c].next=head[u];head[u]=c++;
    	a[c].to=u;a[c].w=0;a[c].next=head[v];head[v]=c++;
    }
    bool bfs(){
    	int u,v;
    	queue<int> q;
    	for(int i=s;i<=t;i++)deep[i]=0;
    	deep[s]=1;
    	q.push(s);
    	while(!q.empty()){
    		u=q.front();
    		q.pop();
    		for(int i=head[u];i;i=a[i].next){
    			v=a[i].to;
    			if(a[i].w&&!deep[v]){
    				deep[v]=deep[u]+1;
    				if(v==t)return true;
    				q.push(v);
    			}
    		}
    	}
    	return false;
    }
    long long dfs(int x,long long limit){
    	if(x==t)return limit;
    	int v;
    	long long sum,cost=0;
    	for(int i=head[x];i;i=a[i].next){
    		v=a[i].to;
    		if(a[i].w&&deep[v]==deep[x]+1){
    			sum=dfs(v,min(a[i].w,limit-cost));
    			if(sum>0){
    				a[i].w-=sum;
    				a[i^1].w+=sum;
    				cost+=sum;
    				if(cost==limit)break;
    			}
    			else deep[v]=-1;
    		}
    	}
    	return cost;
    }
    long long dinic(){
    	long long ans=0;
    	while(bfs())ans+=dfs(s,MAX);
    	return ans;
    }
    inline void clean(){
    	c=2;
    	memset(head,0,sizeof(head));
    	memset(a,0,sizeof(a));
    }
    bool check(long long x){
    	clean();
    	for(int i=1;i<=m;i++)add(s,i,x*attack[i]);
    	for(int i=1;i<=n;i++)add(i+m,t,blood[i]);
    	for(int i=1;i<=m;i++)
    	for(int j=1;j<=n;j++)
    	if(edge[i][j])add(i,j+m,MAX);
    	long long now=dinic();
    	return (now<sum?true:false);
    }
    void work(){
    	long long l=0,r=100000000000LL,mid;
    	while(l<=r){
    		mid=l+r>>1;
    		if(check(mid))l=mid+1;
    		else r=mid-1;
    	}
    	printf("%.6lf
    ",(double)l/10000.00);
    }
    void init(){
    	n=read();m=read();
    	s=0;t=n+m+1;
    	for(int i=1;i<=n;i++){
    		blood[i]=10000LL*read();
    		sum+=blood[i];
    	}
    	for(int i=1;i<=m;i++)attack[i]=read();
    	for(int i=1;i<=m;i++)
    	for(int j=1;j<=n;j++)
    	edge[i][j]=read();
    }
    int main(){
    	init();
    	work();
        return 0;
    }
    
  • 相关阅读:
    Python-Basis-9th
    Python-Basis-8th
    Python-Basis-7th
    Ubuntu-Basis-4th
    Ubuntu-Basis-3rd
    Ubuntu-Basis-2nd
    Ubuntu-Basis-1st
    疯狂java第五章&&第六章-面向对象
    疯狂java第四章-流程控制与数组
    疯狂java第三章-数据类型和运算符
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9519890.html
Copyright © 2011-2022 走看看