1. 程式人生 > >BZOJ3993: [SDOI2015]星際戰爭

BZOJ3993: [SDOI2015]星際戰爭

log Go find math 接下來 href 網絡 LG tex

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軍團的所有巨型機器人

題目傳送門

一眼二分+最大流

莫非網絡流代碼抄多了自帶升級效果???

ST---->i 能夠造成的傷害

i---->j 能打的機器人,INF

j----> ed 護甲值

然後枚舉時間就OK了

喪心病狂這道題竟然卡我精度

代碼如下:

#include<cmath>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define eps 1e-7
using namespace std;
double INF=(1<<29);
struct dicnic{
    int x,y,next,other;
    double c;
}a[2100000];int len,last[210000];
void ins(int x,int y,double c)
{
    int k1,k2;
    k1=++len;
    a[len].x=x;a[len].y=y;a[len].c=c;
    a[len].next=last[x];last[x]=len;
    
    k2=++len;
    a[len].x=y;a[len].y=x;a[len].c=0;
    a[len].next=last[y];last[y]=len;
    
    a[k1].other=k2;
    a[k2].other=k1;
}
int st,ed,head,tail;
int h[210000],list[210000];
bool bt_h()
{
    memset(h,0,sizeof(h));h[st]=1;
    list[1]=st;head=1;tail=2;
    while(head!=tail)
    {
        int x=list[head];
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            if(h[y]==0&&a[k].c>0)
            {
                h[y]=h[x]+1;
                list[tail++]=y;
            }
        }
        head++;
    }
    if(h[ed]>0)return true;
    return false;
}
double findflow(int x,double f)
{
    if(x==ed)return f;
    double s=0,t;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(h[y]==h[x]+1&&a[k].c>0&&s<f)
        {
            s+=(t=findflow(y,min(a[k].c,f-s)));
            a[k].c-=t;a[a[k].other].c+=t;
        }
    }
    if(s==0)h[x]=0;
    return s;
}
int n,m;
double b[51];
double c[51];
int f[51][51];
bool check(double x)
{
    double sum=0.0;
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=m;i++)ins(st,i,x*c[i]);
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            if(f[i][j]==1)
                ins(i,j+m,INF);
    for(int i=1;i<=n;i++)ins(i+m,ed,b[i]),sum+=b[i];
    double ans=0.0;
    while(bt_h()==true)ans+=findflow(st,INF);
    if(abs(ans-sum)<=eps)return true;
    return false;
}
int main()
{
    scanf("%d%d",&n,&m);st=0,ed=n+m+1;
    len=0;memset(last,0,sizeof(last));    
    for(int i=1;i<=n;i++)scanf("%lf",&b[i]);    
    for(int i=1;i<=m;i++)scanf("%lf",&c[i]);
    for(int i=1;i<=m;i++)
        for(int j=1;j<=n;j++)
            scanf("%d",&f[i][j]);
    double l=0.0,r=10000000.0;double ans;
    while(l<=r)
    {
        double mid=(l+r)/2;
        if(check(mid)==true){r=mid-eps;ans=mid;}
        else l=mid+eps;
    }
    printf("%.6lf\n",ans);
    return 0;
}

by_lmy

BZOJ3993: [SDOI2015]星際戰爭