[zjoi2010]cheese
题目:
贪吃的老鼠(cheese.c/cpp/pas/in/out)
时限:每个测试点10秒
[问题描述]
奶酪店里最近出现了m只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉。奶酪店中一天会生产n块奶酪,其中第i块的大小为pi,会在第ri秒被生产出来,并且必须在第di秒之前将它吃掉。第j只老鼠吃奶酪的速度为sj,因此如果它单独吃完第i快奶酪所需的时间为pi/sj。老鼠们吃奶酪的习惯很独特,具体来说:
(1) 在任一时刻,一只老鼠最多可以吃一块奶酪;
(2) 在任一时刻,一块奶酪最多被一只老鼠吃。
由于奶酪的保质期常常很短,为了将它们全部吃掉,老鼠们需要使用一种神奇的魔法来延长奶酪的保质期。将奶酪的保质期延长T秒是指所有的奶酪的di变成di+T。同时,使用魔法的代价很高,因此老鼠们希望找到最小的T使得可以吃掉所有的奶酪。
[输入数据]
输入文件的第一行包含一个整数K,表示输入文件中数据的组数。
每组数据的第一行包含两个整数n和m,分别表示奶酪和老鼠的数量。接下来的n行每行包含三个整数pi,ri,di。最后m行每行包含一个整数,表示sj。pi,ri,di,sj的含义如上文所述。
[输出数据]
输出文件中包含K行,每行包含一个实数,表示你找到的最小的T。你的答案和标准答案的绝对误差不应超过。
输入样例
2
2 2
13 0 4
10 1 3
4
2
1 1
1 0 2
1
输出样例
0.5
0
样例说明
第一组数据中:
l 第0到第1秒:第一只老鼠吃第一块奶酪;
l 第1到第3.5秒:
- 第一只老鼠吃第二块奶酪;
- 第二只老鼠吃第一块奶酪;
l 第3.5到第4.5秒:第一只老鼠吃第一块奶酪。
[数据范围]
思路:
很好的一道题。。可惜我太弱了。。只想到要二分+网络流判定。。然后就什么也不会了。。只能看了题解。。
本题比较难的是一个时间点只能有一只老鼠,而一个老鼠一个时间点只能吃一个。。
朴素的建图是:
让S向每个奶酪连边,流量为pi
把老鼠按照时间段拆点,然后对于每个点, 向T连边,流量为该时间段能吃掉的奶酪数量
并且把奶酪向每个时间段的老鼠连边,流量为流量为该时间段能吃掉的奶酪数量
最后判断是否满流。。
但是,这样会出现有一个时间点有两只老鼠吃完的情况。。。怎么办?
题解就很巧了。。
我们对老鼠吃的速度也进行分段, 每段为对于前一只老鼠的速度差。。
试想一下,如果一个奶酪一个时间段(长度为T)内有若干只老鼠吃了,不妨设为为3只老鼠,a1,a2,a3,并且速度为s1,s2,s3, 同样假设s1< s2 < s3,
那么是不是这一段时间内老鼠吃了T1*s1 + T2(s2-s1) + T3*(s3-s2)
那是不是就可以把老鼠某个时间段吃的方案等价于多少个速度差吃的方案~~
so,构图如下:
让S向每个奶酪连边,流量为pi
对于每个速度段(第j段为sj)进行拆点为vij'按照时间段(假设时间长为t)拆点,然后对于每个点, 向T连边,流量为该时间段该速度段sj在t时间内的产(sj*t*j)
并且把奶酪向每个时间段的速度段vij连边,流量为sj*t
最后判断是否满流。。
这样一来,每个速度段在每个时间段最多只有出现一个,这样就满足一对一的情况。。
好吧。。说的很混乱。。直接上代码吧。。
code:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#define maxn 1200
#define Inf 0x3fffffff
#define maxm 210000
#define eps 1e-8
#define M0(a) memset(a, 0, sizeof(a))
using namespace std;
int cmp(double x, double y){
return fabs(x - y) <= eps;
}
int sgn(double x){
return (x > eps) - (x < -eps);
}
struct oo{
int y, next;
double f;
};
struct MaxFlow{
int n, S, T, tot;
int son[maxn], dist[maxn], gap[maxn];
oo e[maxm];
double sap(int x, double aug){
if (x == T) return aug;
int mind = n;
double sum = , f;
for (int p = son[x]; p != -; p = e[p].next){
int y = e[p].y;
if (dist[y] + == dist[x] && e[p].f){
f = sap(y, min(e[p].f, aug - sum));
e[p].f -= f;
e[p^].f += f;
sum += f;
if (sum == aug || dist[S] >= n) return sum;
}
if (e[p].f) mind = min(mind, dist[y]);
}
if (!sum){
if (!(--gap[dist[x]])) dist[S] = n;
++gap[dist[x] = mind + ];
}
return sum;
} void add(int x, int y, double f){
e[tot].y = y; e[tot].f = f;
e[tot].next = son[x]; son[x] = tot++;
e[tot].y = x; e[tot].f = ;
e[tot].next = son[y]; son[y] = tot++;
} void init(int S, int T, int n){
memset(son, -, sizeof(son));
tot = ;
this->S = S, this->T = T, this->n = n;
}
double maxflow(){
M0(gap);
M0(dist);
gap[] = n;
double ans = ;
while (dist[S] < n) ans += sap(S, Inf);
return ans;
}
} F;
int n, m, p[maxn], r[maxn], d[maxn], s[maxn]; void init(){
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i)
scanf("%d%d%d", &p[i], &r[i], &d[i]);
for (int i = ; i <= m; ++i)
scanf("%d", &s[i]);
sort(s+, s++m, greater<int>());
for (int i = ; i < m; ++i)
s[i] -= s[i+];
} int check(double add){
vector<double> v;
for (int i = ; i <= n; ++i)
v.push_back(r[i]), v.push_back(d[i]+add);
sort(v.begin(), v.end());
v.erase(unique(v.begin(), v.end(), cmp), v.end());
int S = , T = m*(v.size()-)+n+;
F.init(, T, T+);
for (int i = ; i <= n; ++i)
F.add(S, i, p[i]);
for (int i = ; i + < (int)v.size(); ++i){
double dur = v[i+]-v[i];
for (int j = ; j <= m; ++j)
F.add(i * m + n + j, T, j*s[j]*dur);
for (int j = ; j <= n; ++j)
if (sgn(r[j]-v[i]) <= && sgn(d[j]+add-v[i+]) >= )
for (int k = ; k <= m; ++k)
F.add(j, n+i*m+k, dur*s[k]);
}
double sum = ;
for (int i = ; i <= n; ++i)
sum += p[i];
double flow = F.maxflow();
return sgn(flow - sum) == ;
} void solve(){
double l = , r = ;
for (int i = ; i < ; ++i){
double mid = (l + r) / 2.0;
check(mid) ? r = mid : l = mid;
}
printf("%.7lf\n", l);
} int main(){
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
int T;
scanf("%d", &T);
while (T--){
init();
solve();
}
}
[zjoi2010]cheese的更多相关文章
- Luogu P2570 [ZJOI2010]贪吃的老鼠
Luogu P2570 [ZJOI2010]贪吃的老鼠 题目描述 奶酪店里最近出现了\(m\)只老鼠!它们的目标就是把生产出来的所有奶酪都吃掉.奶酪店中一天会生产\(n\)块奶酪,其中第\(i\)块的 ...
- CF 371B Fox Dividing Cheese[数论]
B. Fox Dividing Cheese time limit per test 1 second memory limit per test 256 megabytes input standa ...
- [BZOJ1833][ZJOI2010]count 数字计数
[BZOJ1833][ZJOI2010]count 数字计数 试题描述 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. 输入 输入文件中仅包含一行两个整数a ...
- hdu 1078 FatMouse and Cheese
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...
- HDU 1078 FatMouse and Cheese(记忆化搜索)
FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Othe ...
- ZOJ 1107 FatMouse and Cheese
原题链接 题目大意:FM在一个街道n*n街道的(0,0)点,在每个网格里放着cheese,他要尽可能多的吃这些cheese.有两个规则:1)他跑的总距离不能超过k步:2)下一个节点的cheese的块数 ...
- Codeforces Round #218 (Div. 2) B. Fox Dividing Cheese
B. Fox Dividing Cheese time limit per test 1 second memory limit per test 256 megabytes input standa ...
- hdu 1078 FatMouse and Cheese (dfs+记忆化搜索)
pid=1078">FatMouse and Cheese Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/ ...
- AOJ 0558 Cheese
Cheese Time Limit : 8 sec, Memory Limit : 65536 KB チーズ (Cheese) 問題 今年も JOI 町のチーズ工場がチーズの生産を始め,ねずみが巣から ...
随机推荐
- BPF+XDP比较全的资料都在这里
Dive into BPF: a list of reading material Sep 1, 2016 • Quentin Monnet◀Table of contents What is BPF ...
- POJ2349 Arctic Network
原题链接 先随便找一棵最小生成树,然后贪心的从大到小选择边,使其没有贡献. 显然固定生成树最长边的一个端点安装卫星频道后,从大到小选择边的一个端点作为卫星频道即可将该边的贡献去除. 所以最后的答案就是 ...
- MySQL 检索数据及提高检索速度的方法
检索数据 mysql> SELECT [DISTINCT] 表名.列名,表名.列名,表名.列名 -- 使用通配符*表示所有列 DISTINCT表示返回不同的值 -> FROM 数据库名.表 ...
- Python 常用模块之re 正则表达式的使用
re模块用来使用正则表达式.正则表达式用来对字符串进行搜索的工作.我们最应该掌握正则表达式的查询,更改,删除的功能.特别是做爬虫的时候,re模块就显得格外重要. 1.查询 import re a = ...
- 【记录】解决VS2015调试Xamarin程序一闪而过(使用微软ANDROID模拟器)
越来越多的人去安装Visual Studio 2015,也会去试试其中的C#跨平台开发利器Xamarin,但是也会发现很多问题. 我相信我不会是唯一遇到以下问题的,也不会是最后一个,特此记录. 微软的 ...
- 【Web】Nginx 反向代理与负载均衡
反向代理 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客 ...
- MySQL中使用SHOW PROFILE命令分析性能的用法整理
show profile是由Jeremy Cole捐献给MySQL社区版本的.默认的是关闭的,但是会话级别可以开启这个功能.开启它可以让MySQL收集在执行语句的时候所使用的资源.为了统计报表,把pr ...
- virtual、abstract、interface区别以及用法
virtual 用于在基类中的使用的方法,使用的情况为: 情况1:在基类中定义了virtual方法,但在派生类中没有重写该虚方法.那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法. ...
- 836. Rectangle Overlap
class Solution { public: bool isRectangleOverlap(vector<int>& rec1, vector<int>& ...
- Mysql 数据库修改datadir和调整默认引擎要注意的问题
数据库更改 datadir 默认位置: 首先前面的基础操作我就不多说了,无非是复制mysqldata目录,然后修改 my.conf 配置文件 datadir 的 路径地址.然后重启mysql.这里可能 ...