题目:

贪吃的老鼠(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();
}
}

 

最新文章

  1. ElasticSearch 5学习(8)——分布式文档存储(wait_for_active_shards新参数分析)
  2. js获取Html元素的实际宽度高度
  3. lambda的使用ret = filter(lambda x : x &gt; 22 ,[11,22,33,44])
  4. c# 操作xml题目
  5. 修改placeholder颜色
  6. C#下如何用NPlot绘制期货股票K线图(2):读取数据文件让K线图自动更新
  7. 生成N个不重复的随机数(转)
  8. C# 利用SMTP异步发送邮件
  9. android开发用无线网络进行Android开发中的调试
  10. 使用dom4j 解析xml文件
  11. jquery怎么选择嵌套的第一层的li
  12. CSS之img标签
  13. java学习第04天(语句、函数、数组)
  14. [JS] console.time() - 计时器构造函数及如何计时
  15. cordova / Ionic 开发问题汇总
  16. 一款基于jquery滑动后固定于顶部的导航
  17. Python开发一个WEB聊天室
  18. c语言静态断言
  19. 如何写出高性能SQL语句
  20. 【Codeforces】Round #491 (Div. 2) 总结

热门文章

  1. 探索未知种族之osg类生物---起源
  2. POJ 2449Remmarguts&#39; Date 第K短路
  3. MySQL学习笔记-数据库后台线程
  4. UI设计初学者教程:色彩基础知识
  5. PHP 获取当前所在的类名、方法名等
  6. coocsCreator杂记
  7. java进行3DES加解密
  8. Time的各种变量unity3d
  9. kbmmw 中的日期时间操作
  10. mfc标题栏 菜单 退出 关机 重启