bzoj3993: [SDOI2015]星际战争

来源:互联网 发布:国际版的中国软件 编辑:程序博客网 时间:2024/05/09 01:42

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

题解

不知道为什么,一看题就觉得是二分网络流。。
我们就二分答案x,然后st连向每个炮塔,连x*b的攻击力,炮塔连向他能达到的地方,机器人连向ed,流量是a
看下是否满流就好了

出题人良心,不卡精度,但我为了避免精度,我还是把它转为整数了

#include<cstdio>#include<cstdlib>#include<algorithm>#include<iostream>#include<queue>#include<cstring>using namespace std;typedef long long LL;const LL MAX=1LL<<55;const LL N=55*2;const LL ADD=10000;LL a[N],b[N];//装甲值    攻击力 LL n,m;LL c[55][55];//第i个炮可以打到谁struct qq{LL x,y,z,last;}s[55*56*2];LL num,last[N];LL st,ed;void init (LL x,LL y,LL z){    num++;    s[num].x=x;s[num].y=y;s[num].z=z;    s[num].last=last[x];    last[x]=num;    swap(x,y);z=0;    num++;    s[num].x=x;s[num].y=y;s[num].z=z;    s[num].last=last[x];    last[x]=num;}LL h[N];bool Bt (){    memset(h,-1,sizeof(h));h[st]=1;    queue<int> q;    q.push(st);    while (!q.empty())    {        LL x=q.front();q.pop();        for (LL u=last[x];u!=-1;u=s[u].last)        {            LL y=s[u].y;            if (s[u].z>0&&h[y]==-1)            {                h[y]=h[x]+1;                q.push(y);            }        }    }    return h[ed]!=-1;}LL mymin (LL x,LL y){return x<y?x:y;}LL dfs (LL x,LL f){    if (x==ed) return f;    LL s1=0;    for (LL u=last[x];u!=-1;u=s[u].last)    {        LL y=s[u].y;        if (s[u].z>0&&h[y]==h[x]+1&&s1<f)        {            LL lalal=dfs(y,mymin(s[u].z,f-s1));            s1+=lalal;            s[u].z-=lalal;            s[u^1].z+=lalal;        }    }    if (s1==0) h[x]=-1;    return s1;}bool check (LL x){    LL shen=0;    num=1;memset(last,-1,sizeof(last));    for (LL u=1;u<=n;u++)     {        init(st,u,a[u]);        shen+=a[u];    }    for (LL u=1;u<=m;u++) init(u+n,ed,b[u]*x);    for (LL u=1;u<=m;u++)        for (LL i=1;i<=n;i++)            if (c[u][i])                init(i,u+n,MAX);    while (Bt()==true) shen=shen-dfs(st,MAX);    return shen==0;}int main(){    scanf("%lld%lld",&n,&m);st=n+m+1;ed=st+1;    for (LL u=1;u<=n;u++)       {        scanf("%lld",&a[u]);        a[u]*=ADD;    }    for (LL u=1;u<=m;u++)   scanf("%lld",&b[u]);    for (LL u=1;u<=m;u++)        for (LL i=1;i<=n;i++)            scanf("%lld",&c[u][i]);    LL l=0,r=1000*50*ADD;//时间是多少    LL ans=0;    while (l<=r)    {        LL mid=(l+r)>>1;        if (check(mid)) {r=mid-1;ans=mid;}        else l=mid+1;    }    printf("%lf\n",(double)ans/(double)ADD);    return 0;}