传送门:https://www.luogu.org/problemnew/show/P3324

首先瞅一眼数据范围,发现m, n都很小,所以就可以初步断定这是一道网络流的题。

因为题中说每一个武器只能攻击特定的机器人,所以可以想象成这把武器有一条指向该机器人的边,那流量是多少呢?这是不确定的,因为武器攻击机器人的策略是不知道的。不过有一点可以确定,就是在时间t内,这把武器造成的伤害一定是b[i] * t,如果把武器i和源点连一条边,那么这条边的容量就是b[i] * t。

在考虑每一个机器人的装甲值,如果给个机器人i和汇点建立一条边,那么容量就是a[i]。这样我们就成功建立了一个图。

然后对 t 进行二分,如果在当时间为 t 时,到汇点的流量是sum(a[i]),那么就说明所有机器人都被打败了,就在左区间二分,否则说明 t 取小了,就在右区间二分。

因为题中说输出结果与标准答案的绝对误差不超过10-3即视为正确,所以我们把防御值扩大10000倍,这样在long long 范围内就可以解决了。

 #include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<stack>
#include<queue>
#include<vector>
using namespace std;
#define enter printf("\n")
#define space printf(" ")
#define Mem(a) memset(a, 0, sizeof(a));
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-;
const int maxn = 2e5 + ;
inline ll read()
{
ll ans = ;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) {last = ch; ch = getchar();}
while(isdigit(ch))
{
ans = ans * + ch - ''; ch = getchar();
}
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar(x % + '');
}
//mrclr// int n, m, t;
ll a[], b[];
bool s[][];
struct Edge
{
int from, to;
ll cap, flow;
};
vector<Edge> edges;
vector<int> G[maxn]; void init()
{
edges.clear();
for(int i = ; i < maxn; ++i) G[i].clear(); }
void addEdge(int from, int to, ll w) //以下就是网络流的板子了
{
edges.push_back((Edge){from, to, w, });
edges.push_back((Edge){to, from, , });
int sz = edges.size();
G[from].push_back(sz - );
G[to].push_back(sz - );
} int dis[maxn];
bool vis[maxn];
bool bfs()
{
Mem(vis);
queue<int> q;
q.push(); vis[] = ;
dis[] = ;
while(!q.empty())
{
int now = q.front(); q.pop();
for(int i = ; i < (int)G[now].size(); ++i)
{
Edge& e = edges[G[now][i]];
if(!vis[e.to] && e.cap > e.flow)
{
vis[e.to] = ;
dis[e.to] = dis[now] + ;
q.push(e.to);
}
}
}
return vis[t];
}
int cur[maxn];
ll dfs(int now, ll a)
{
if(now == t || !a) return a;
ll flow = , f;
for(int& i = cur[now]; i < (int)G[now].size(); ++i)
{
Edge& e = edges[G[now][i]];
if(dis[e.to] == dis[now] + && (f = dfs(e.to, min(a, e.cap - e.flow))) > )
{
e.flow += f;
edges[G[now][i] ^ ].flow -= f;
flow += f; a -= f;
if(!a) break;
}
}
return flow;
} ll maxflow()
{
ll flow = ;
while(bfs())
{
Mem(cur);
flow += dfs(, (ll)INF * INF);
}
return flow;
} ll sum = ; bool judge(ll tp)
{
init();
for(int i = ; i <= m; ++i) addEdge(, i, b[i] * tp); //把武器和源点建立一条容量为b[i] * time 的边
for(int i = ; i <= n; ++i) addEdge(i + m, t, a[i]); //把机器人和汇点建立一条容量为a[i]的边
for(int i = ; i <= m; ++i)
for(int j = ; j <= n; ++j)
if(s[i][j]) addEdge(i, j + m, INF);
//如果武器i能攻击机器人j,就建边,容量无穷,因为武器i有b[i] * time的限制
// printf("%lld %lld\n", maxflow(), sum);
//调试的时候请不要这么写,因为maxflow()跑完后已经成残量网络了,在上面跑自然不对
return maxflow() == sum;
} int main()
{
n = read(); m = read(); //防御值扩大1e4倍
t = n + m + ;
for(int i = ; i <= n; ++i) {a[i] = read(); a[i] *= ; sum += a[i];}
for(int i = ; i <= m; ++i) b[i] = read();
for(int i = ; i <= m; ++i)
for(int j = ; j <= n; ++j)
{int x = read(); s[i][j] = x;}
ll L = , R = (ll)INF * (ll)INF;
while(L < R)
{
int mid = (L + R) >> ;
if(judge(mid)) R = mid;
else L = mid + ;
}
printf("%.5lf\n", (double)L / );
return ;
}

P3324 [SDOI2015]星际战争的更多相关文章

  1. 洛谷P3324 [SDOI2015]星际战争

    题目:洛谷P3324 [SDOI2015]星际战争 思路: 类似<导弹防御塔>,因为题目保证有解,花费时间小于最终答案时一定无法消灭所有敌人,只要花费时间大于等于最终答案都可以消灭所有敌人 ...

  2. BZOJ 3993 Luogu P3324 [SDOI2015]星际战争 (最大流、二分答案)

    字符串终于告一段落了! 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=3993 (luogu) https://www.l ...

  3. 洛谷P3324 [SDOI2015]星际战争 题解

    题目链接: https://www.luogu.org/problemnew/show/P3324 分析: 因为本题的时间点较多,不能枚举,但发现有单调性,于是二分答案,二分使用的时间TTT 每个攻击 ...

  4. 洛谷$P3324\ [SDOI2015]$星际战争 网络流+二分

    正解:网络流+二分 解题报告: 传送门$QwQ$ 其实我第一反应是费用流来着,,,但是仔细想了下发现我不会实现各个武器之间独立同时?而且攻击是连续的答案可能是小数嘛$QwQ$. 所以显然不是递推就二分 ...

  5. Luogu P3324 [SDOI2015]星际战争

    二分+最大流 首先考虑二分答案 然后可以发现对于已知时间,判断是否可以将所有机器人摧毁可以用网络流 建立源点和汇点,源点向每一个激光武器连一条容量为$time*b[i]$的边,表示该激光武器在$tim ...

  6. BZOJ 3993: [SDOI2015]星际战争 [二分答案 二分图]

    3993: [SDOI2015]星际战争 题意:略 R1D2T1考了裸二分答案+二分图最大匹配... #include <iostream> #include <cstdio> ...

  7. BZOJ_3993_[SDOI2015]星际战争_二分+网络流

    BZOJ_3993_[SDOI2015]星际战争_二分+网络流 Description 3333年,在银河系的某星球上,X军团和Y军团正在激烈地作战.在战斗的某一阶段,Y军团一共派遣了N个巨型机器人进 ...

  8. bzoj千题计划131:bzoj3993: [SDOI2015]星际战争

    http://www.lydsy.com/JudgeOnline/problem.php?id=3993 二分答案 源点向武器连 mid*攻击力的边 机器人向汇点连 防御力 的边 武器i能攻击机器人j ...

  9. 3993: [SDOI2015]星际战争

    3993: [SDOI2015]星际战争 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1244  Solved: ...

随机推荐

  1. Java迭代器的一般用法

    迭代器(Iterator) 迭代器是一种设计模式,它是一个对象,它可以遍历并选择序列中的对象,而开发人员不需要了解该序列的底层结构.迭代器通常被称为“轻量级”对象,因为创建它的代价小. Java中的I ...

  2. Java-函数式编程(二)Lambda表达式

    本文首发:Java-函数式编程(二)Lambda表达式 “Lambda 表达式”(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lamb ...

  3. 面试中常问的List去重问题,你都答对了吗?

    面试中经常被问到的list如何去重,用来考察你对list数据结构,以及相关方法的掌握,体现你的java基础学的是否牢固. 我们大家都知道,set集合的特点就是没有重复的元素.如果集合中的数据类型是基本 ...

  4. JAVA设计模式详解(五)----------适配器模式

    各位朋友好,本章节我们继续讲第五个设计模式. 在生活中,我们都知道手机内存卡是无法直接接电脑的,因为内存卡的卡槽比较小,而电脑只有USB插孔,此时我们需要用到读卡器.这个读卡器就相当于是适配器.这是生 ...

  5. Three.js开发指南---粒子和粒子系统(第七章)

    使用粒子可以很容易的创建很多细小的物体,例如雨滴雪花等 本章主要内容: 1 使用ParticleBasicMaterial(基础粒子材质)来创建和设计粒子 2 使用ParticleSystem来创建一 ...

  6. JavaScript--动态加载脚本和样式(23)

    一 动态脚本 // 当网站需求变大,脚本的需求也逐步变大;我们不得不引入太多的JS脚本而降低了整站的性能; // 所以就出现了动态脚本的概念,在适时的时候加载相应的脚本; 1.动态引入js文件 var ...

  7. 设计模式(9)--Composite(组合模式)--结构型

    1.模式定义: 组合模式属于对象的结构模式,有时又叫做“部分——整体”模式.组合模式将对象组织到树结构中,可以用来描述整体与部分的关系.组合模式可以使客户端将单纯元素与复合元素同等看待. 2.模式特点 ...

  8. JdbcTemplate 方法使用

    作者QQ:1095737364    QQ群:123300273     欢迎加入! execute方法:可以用于执行任何SQL语句,一般用于执行DDL语句: update方法及batchUpdate ...

  9. 使用IDEA创建Java Web项目并部署

    前面给大家介绍了IDEA的安装和基本配置,睡觉前Alan再给大家分享一下使用IDEA创建Java Web并部署访问. 打开IDEA,File>New>Project,进入Java Ente ...

  10. git cherry-pick 用法

    1.当合并代码冲突特别多的时候,有时候只想提交自己分支的代码.这个时候使用cherry-pick 可以实现 1)首先使用 git log --oneline -n 找到最近自己分支的提交记录,n表示提 ...