洛谷 P2570 [ZJOI2010]贪吃的老鼠

洛谷 P2570 [ZJOI2010]贪吃的老鼠


题目

题目描述

奶酪店里最近出现了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。你的答案和标准答案的绝对误差不应超过10−4。

输入输出样例

输入样例#1:

2
2 2
13 0 4
10 1 3
4
2
1 1
1 0 2
1

输出样例#1:

0.5
0

说明

样例说明

第一组数据中:

 第0到第1秒:第一只老鼠吃第一块奶酪;

 第1到第3.5秒:

第一只老鼠吃第二块奶酪;

第二只老鼠吃第一块奶酪;
 第3.5到第4.5秒:第一只老鼠吃第一块奶酪。

数据规模

30%的数据中,1≤n,m≤5;

100%的数据中,1≤K≤5,1≤n,m≤30,1≤pi≤10^5, 0 ≤ri

题解

(标签:二分答案+网络流)[应该是正解吧……洛谷上的题解就是这个……]

[先说明下,怕各位看到错误想法后开始往错误的方法上想……,总之,我已经石乐志了]

先贴一个想法吧,,不知道对不对……(要回寝室睡觉了…..代码星期三贴)(想法错了请dalao说明,谢谢)

二分答案+贪心

二分答案就不解释了

贪心:先按生产出来的时间顺序排序,用当前空闲且恰好能在规定的时间内吃完奶酪的老鼠来吃奶酪,并且记录它吃完该奶酪的时间,如果出现当前没有能在规定时间内吃完奶酪的老鼠,那么就用当前速度最大的老鼠,吃的时候如果有某只速度快于它的老鼠吃完某块奶酪,那么就换老鼠,在该只老鼠吃的时候继续更新直到用一只速度尽量小的老鼠吃完这块奶酪,如果依然无法吃完,则说明该延长时间不可行

以上是原来的思路……(经过一天的思考,我有了更进(shí)一(lè)步(zhì)的想法……)

二分我还是不说……

首先,按完成时间的顺序对奶酪排一边序(每次二分答案不需要更新,且保证最应该先完成的奶酪能够先完成)顺序按时间轴排序对时间进行排序(t每更改一次就需要重新更新右边界的位置),然后用双向链表维护时间轴(因为,在吃奶酪的过程中,老鼠并不会全部都恰好在右边界时吃掉奶酪),然后就是在双向链表的基础上过一边时间轴,对于每一个时间点,先做完该时间点与上一个时间点之间的各奶酪的余量,然后,如果在该时间点与下一个时间点中有老鼠吃完奶酪,就需要记录下来并且ret–(当ret==0时就可以return true了),按时间先后分别加入双向链表(未能在该段时间中吃完的奶酪,完成时间依然是原来的右边界),然后,为下一个时间段重新做一遍奶酪与老鼠的分配(尽量用速度小且能吃完奶酪的老鼠,否则就用当前速度最快的老鼠),如果到了某一个奶酪的右边界时间点而奶酪还没吃完,则说明该二分的答案不可行

自己吐槽一句:我可能真的是石乐志了......

更改一下:在中途如果有老鼠吃完奶酪,改时间的时候只需更新最先吃完的那个奶酪以及时间点,其他的不需要更改,因为在做先吃完的奶酪的那个时间点时会重新对剩余的点进行一次更新

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用[1],dp[u][j]表示在u子树中选取恰好j个人时能获得的最大价值。而根据引用,该问题的时间复杂度为O(log2​104×nm)。 对于洛谷P2143 [JSOI2010] 巨额奖金问题,我们可以使用动态规划来解决。具体步骤如下: 1. 首先,我们需要构建一棵树来表示员工之间的关系。树的根节点表示公司的总经理,其他节点表示员工。每个节点都有一个权值,表示该员工的奖金金额。 2. 接下来,我们可以使用动态规划来计算每个节点的dp值。对于每个节点u,我们可以考虑两种情况: - 如果选择节点u,则dp[u][j] = dp[v][j-1] + value[u],其中v是u的子节点,value[u]表示节点u的奖金金额。 - 如果不选择节点u,则dp[u][j] = max(dp[v][j]),其中v是u的子节点。 3. 最后,我们可以通过遍历树的所有节点,计算出dp[u][j]的最大值,即为所求的巨额奖金。 下面是一个示例代码,演示了如何使用动态规划来解决洛谷P2143 [JSOI2010] 巨额奖金问题: ```python # 构建树的数据结构 class Node: def __init__(self, value): self.value = value self.children = [] # 动态规划求解最大奖金 def max_bonus(root, j): dp = [[0] * (j+1) for _ in range(len(root)+1)] def dfs(node): if not node: return for child in node.children: dfs(child) for k in range(j, 0, -1): dp[node.value][k] = max(dp[node.value][k], dp[node.value][k-1] + node.value) for child in node.children: for k in range(j, 0, -1): for l in range(k-1, -1, -1): dp[node.value][k] = max(dp[node.value][k], dp[node.value][k-l-1] + dp[child.value][l]) dfs(root) return dp[root.value][j] # 构建树 root = Node(1) root.children.append(Node(2)) root.children.append(Node(3)) root.children[0].children.append(Node(4)) root.children[0].children.append(Node(5)) root.children[1].children.append(Node(6)) # 求解最大奖金 j = 3 max_bonus_value = max_bonus(root, j) print("最大奖金为:", max_bonus_value) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值