题目描述

3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战。

在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进攻X军团的阵地,其中第i个巨型机器人的装甲值为Ai。当一个巨型机器人的装甲值减少到0或者以下时,这个巨型机器人就被摧毁了。

X军团有M个激光武器,其中第i个激光武器每秒可以削减一个巨型机器人Bi的装甲值。激光武器的攻击是连续的。

这种激光武器非常奇怪,一个激光武器只能攻击一些特定的敌人。Y军团看到自己的巨型机器人被X军团一个一个消灭,他们急需下达更多的指令。

为了这个目标,Y军团需要知道X军团最少需要用多长时间才能将Y军团的所有巨型机器人摧毁。但是他们不会计算这个问题,因此向你求助。

输入输出格式

输入格式:

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

输出格式:

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

输入输出样例

输入样例#1:

2 2
3 10
4 6
0 1
1 1
输出样例#1:

1.300000

说明

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

[spj]

思路:

  二分+最大流;

  轻松ac;

  二分时间,用最大流判断是否能达到装甲总值;

来,上代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm> #define maxn 101
#define INF 9999999.99
#define EFlit 10000.0 using namespace std; struct EdgeType {
int v,e; double f;
};
struct EdgeType edge[maxn*maxn<<]; int if_z,n,m,head[maxn<<],s,t=(maxn<<)-;
int ai[maxn],bi[maxn],tota,totb,map[maxn][maxn];
int deep[maxn<<],cnt; double dai[maxn],dbi[maxn]; char Cget; inline void in(int &now)
{
now=,if_z=,Cget=getchar();
while(Cget>''||Cget<'')
{
if(Cget=='-') if_z=-;
Cget=getchar();
}
while(Cget>=''&&Cget<='')
{
now=now*+Cget-'';
Cget=getchar();
}
now*=if_z;
return ;
} bool bfs()
{
queue<int>que;
memset(deep,-,sizeof(deep));
que.push(s);deep[s]=;
while(!que.empty())
{
int pos=que.front();que.pop();
for(int i=head[pos];i;i=edge[i].e)
{
if(deep[edge[i].v]<&&edge[i].f>)
{
deep[edge[i].v]=deep[pos]+;
if(edge[i].v==t) return true;
que.push(edge[i].v);
}
}
}
return false;
} double flowing(int now,double flow)
{
if(now==t||flow==) return flow;
double oldflow=;
for(int i=head[now];i;i=edge[i].e)
{
if(deep[edge[i].v]==deep[now]+&&edge[i].f>)
{
double pos=flowing(edge[i].v,min(flow,edge[i].f));
if(pos>)
{
flow-=pos;
oldflow+=pos;
edge[i].f-=pos;
edge[i^].f+=pos;
if(flow==) return oldflow;
}
}
}
if(oldflow==) deep[now]=-;
return oldflow;
} inline void edge_add(int u,int v,double f)
{
edge[++cnt].v=v,edge[cnt].f=f,edge[cnt].e=head[u],head[u]=cnt;
edge[++cnt].v=u,edge[cnt].f=,edge[cnt].e=head[v],head[v]=cnt;
} bool check(double ans_)
{
cnt=;
memset(head,,sizeof(head));
for(int i=;i<=m;i++) edge_add(s,i,dbi[i]*ans_);
for(int i=;i<=n;i++) edge_add(i+m,t,dai[i]);
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++)
{
if(map[i][j]) edge_add(i,j+m,INF);
}
}
double pos=;
while(bfs()) pos+=flowing(s,INF);
if(pos>=(double)tota-0.001) return true;
else return false;
} int main()
{
in(n),in(m);
for(int i=;i<=n;i++)
{
in(ai[i]);
tota+=ai[i];
dai[i]=ai[i];
}
for(int i=;i<=m;i++)
{
in(bi[i]);
totb+=bi[i];
dbi[i]=bi[i];
}
for(int i=;i<=m;i++)
{
for(int j=;j<=n;j++) in(map[i][j]);
}
double l=(double)tota/(double)totb,r=EFlit,mid,ans;
// double l=0,r=EFlit,mid,ans;
while(l<r)
{
mid=(l+r)/2.0;
if(check(mid)) ans=mid,r=mid-0.0001;
else l=mid+0.0001;
}
printf("%lf\n",ans);
return ;
}

最新文章

  1. 折叠ListView
  2. 实现Asp.Net Mvc4多级Views目录
  3. Oracle全表扫描
  4. MySQL系列-第一章节:MySQL介绍与安装
  5. Spark分布式计算和RDD模型研究
  6. [PHP] curl访问https与CA证书问题
  7. nginx报错:./configure: error: C compiler cc is not found, gcc 是已经安装了的
  8. 第一部分牛刀小试:启动GDB开始调试
  9. 推荐系统模型之 FM
  10. topcoder srm 580 div1
  11. 一次永久解决cmd窗口汉字显示乱码
  12. MySQL Binlog--MIXED模式下数据更新
  13. Centos 安装Sublime text 3
  14. 消息推送SignalR简单实例
  15. layui实现复选框全选,反选
  16. C#编程(十八)----------C#中的结构
  17. 设计模式之————依赖注入(Dependency Injection)与控制反转(Inversion of Controller)
  18. JUC回顾之-线程池的原理和使用
  19. JS获取select的value和text值的简单实例
  20. WPF 中使用附加属性,将任意 UI 元素或控件裁剪成圆形(椭圆)

热门文章

  1. (74)zabbix第三方认证之http(nginx basic auth)
  2. Tourists Gym - 101002I LCA——dfs+RMQ在线算法
  3. LA 3790 Overlapping Squares DFS
  4. python小数据池,代码块深入剖析
  5. 中国首届CSS开发者大会讲师照片
  6. 树状数组 - BZOJ 1103 [POI2007]大都市
  7. 大数据学习——SparkStreaming整合Kafka完成网站点击流实时统计
  8. 如何在 Rails 中搭配 Turbolinks 使用 Vue
  9. [整理]Linux下的源码安装步骤及其功能解释
  10. POJ 1145 Tree Summing