分析解决方案无疑是矫枉过正......但是,嘿,我喜欢矫枉过正。
首先,我转化cuts
为 y=mx+b 格式:
cuts = [(k, (v1-100)*0.01,-v0) for k,(v0,v1) in cuts.items()]
cuts.sort()
导致
cuts = [
('Brilliant', 2.5, -250),
('Crystal Ball', 1.6, -100),
('Emerald', 0.25, -10),
('Heart-shaped', 4.0, -1000),
('Marquis', 1.3, -75),
('Oval', 0.5, -20),
('Pear', 0.75, -35),
('Plumbbob', 1.0, -50),
('Star Cut', 3.0, -400)
]
对于每对切割,我可以找到交点 - 两个切割值相同的宝石尺寸
from itertools import combinations
xints = []
for (na,ma,ba),(nb,mb,bb) in combinations(cuts, 2):
xint = (bb-ba)/(ma-mb)
val = ma*xint + ba
# figure out which cut dominates to the right
va = ma*(xint+0.01)+ba
vb = mb*(xint+0.01)+bb
if vb > va:
xints.append((xint,val,na,nb))
else:
xints.append((xint,val,nb,na))
这会产生 36 个交叉点,其中大部分是多余的 - 在这一点上,其他一些切割更有价值。所以我们过滤:
xints = [(xint,val,na,nb) for xint,val,na,nb in xints if all(nc==na or nc==nb or mc*xint+bc <= val for nc,mc,bc in cuts)]
xints.sort()
留下 10 个有效的交叉点:
[
(40.0, 0.0, 'Emerald', 'Oval'),
(60.0, 10.0, 'Oval', 'Pear'),
(60.0, 10.0, 'Oval', 'Plumbbob'),
(60.0, 10.0, 'Pear', 'Plumbbob'),
(83.33333333333331, 33.333333333333314, 'Marquis', 'Crystal Ball'),
(83.33333333333331, 33.333333333333314, 'Plumbbob', 'Crystal Ball'),
(83.33333333333331, 33.333333333333314, 'Plumbbob', 'Marquis'),
(166.66666666666669, 166.66666666666674, 'Crystal Ball', 'Brilliant'),
(300.0, 500.0, 'Brilliant', 'Star Cut'),
(600.0, 1400.0, 'Star Cut', 'Heart-shaped')
]
通过检查,我们看到 Pear 和 Marquis 切割是多余的——它们仅在交叉点处具有竞争力——因此我们丢弃它们出现的 4 个项目,得到
[
(40.0, 0.0, 'Emerald', 'Oval'),
(60.0, 10.0, 'Oval', 'Plumbbob'),
(83.33333333333331, 33.333333333333314, 'Plumbbob', 'Crystal Ball'),
(166.66666666666669, 166.66666666666674, 'Crystal Ball', 'Brilliant'),
(300.0, 500.0, 'Brilliant', 'Star Cut'),
(600.0, 1400.0, 'Star Cut', 'Heart-shaped')
]
哪些是最佳交叉点;然后你的桌子最终看起来像
Size Value Cut
---- ----- ------------
0 -10
Emerald
40 0
Oval
60 10
Plumbbob
83.33 33.33
Crystal Ball
166.67 166.67
Brilliant
300 500
Star Cut
600 1400
Heart-shaped
严格来说,您可能会丢弃祖母绿切割,因为预期值是负数(对任何小于 40 的宝石进行切割都会让您损失金钱)。