[蓝桥杯 2024 国 Python B] 工厂
LargeRice16pro · · 题解
拓扑排序做法。
注意到:
考虑最后售卖的物品,容易发现:最终卖出去的一定只是某一个物品,不会卖出多个物品。简单理解就是因为要求性价比最大,那么多个物品的性价比加起来一定不会超过这些物品中性价比最大的那个(糖水不等式)。
且工人的生产决策只与数量相关,与物品价格无关,所以只需要考虑数量和工人数之比。
所以,在 DAG 上 dp 即可:
那么转移边
注意:此处分数不能约分,因为分母表示的是工人数量,具有实际意义。因为题目限制了
最后再考虑
因为具体实现中的
DAG 上 dp 采用拓扑排序实现,时间复杂度:
from collections import deque
from math import *
n, m = map(int, input().split())
a = list(map(int, input().split()))
x = [0 for _ in range(m)]
y = [0 for _ in range(m)]
k = [0 for _ in range(m)]
w = [0 for _ in range(m)]
p = [[] for _ in range(n)]
deg = [0 for _ in range(n)]
def add(x, y, k, w):
p[x].append([y, k, w])
deg[y] += 1
dp = [[0,1] for _ in range(n)]
def max(x, y):
if x[0] * y[1] > y[0] * x[1]:
return x
return y
b = [[0, 1] for _ in range(n)]
for i in range(m):
x[i], y[i], k[i], w[i] = map(int, input().split())
x[i] -= 1
y[i] -= 1
if k[i] == 0:
dp[y[i]] = max(dp[y[i]], [w[i], 1])
else:
if x[i] == y[i]:
b[x[i]] = max(b[x[i]], [w[i], k[i]])
else:
add(x[i], y[i], k[i], w[i])
q = deque()
for i in range(n):
if not deg[i]:
q.append(i)
while q:
now = q.popleft()
if b[now][0] and dp[now][0]:
b[now][0], b[now][1] = b[now][1], b[now][0]
fz = b[now][1] * lcm(dp[now][0], b[now][0]) // b[now][0]
fm = dp[now][1] * lcm(dp[now][0], b[now][0]) // dp[now][0]
fm = fm + lcm(dp[now][0], b[now][0]) // b[now][0]
dp[now] = max(dp[now], [fz, fm])
for v in p[now]:
fz, fm = 0, 1
if dp[now][0] != 0:
fz = v[2] * lcm(dp[now][0], v[1]) // v[1]
fm = dp[now][1] * lcm(dp[now][0], v[1]) // dp[now][0]
fm = fm + lcm(dp[now][0], v[1]) // v[1]
dp[v[0]] = max(dp[v[0]], [fz, fm])
deg[v[0]] -= 1
if not deg[v[0]]:
q.append(v[0])
ans = [0, 1]
for i in range(n):
dp[i][0] *= a[i]
ans = max(ans, dp[i])
res = ans[0] / ans[1]
print(f"{res:.2f}")