问题: 您是一家寻找最佳供应商的果汁生产商。供应商正在销售含有3种成分的浓缩物:X:Y:Z的比例不同。你的果汁需要这些比例为1:1:1,否则它不会很好吃。浓缩物的重量是其成分的总和(以磅为单位),所有供应商都以相同的价格出售其浓缩物,但是您的卡车只能携带高达400磅的浓缩物。 为您的企业找到最好的供应商:购买(找到)尽可能多的浓缩物(但少于400磅),知道1:1:1以外的成分比例是不可接受的。
输入: 第一行告诉您市场上销售的浓缩物数量(少于200个) 接下来的n行是关于浓缩物的X:Y:Z成分(以磅为单位)的比例
输出: 第一行应该是您要购买的浓缩物成分的重量总和(小于400磅) 第二行应该告诉您需要购买多少浓缩物以使这个数量保持适当的比例
示例:
in:
4 //how many concentrates are sold on the market
1 2 3 //first concentrate contains 1lb of X, 2lbs of Y, 3 lbs of Z
0 4 1
1 3 4
1 1 1
2 1 0
out:
12 //4lbs of ingredient X + 4lbs Y + 4lbs Z
3 //we're buying three concentrates: the first one, fourth and fifth (1 2 3; 1 1 1; 2 1 0) so we're getting the biggest amount of it with 1:1:1 ratio of ingredients
我的解决方案: 我的解决方案是一种蛮力方法,当有很多供应商时它非常慢,因为它的复杂性是2 ^(n-2) - 这个算法只会创建我们可以购买的浓缩物的所有可能组合,它会检查它们是否是比例是1:1:1,如果是,那么它会比较它们,找到总成分总量小于400磅的那个。
我正在寻找一种动态逼近算法,但是,我不知道如何使用适当的比率约束来做到这一点。
答案 0 :(得分:3)
400/3 = 133
这意味着答案的任何成分不得超过133磅。因此,DP阵列为array[134][134][134]
,其中阵列中的每个条目都是要购买的集中数,以实现该组合。
该阵列中有大约240万个条目,每个输入需要扫描一次(小于200)。因此,您正在寻找大约5亿次操作来填充阵列。这在现代计算机上是合理的。
填充数组后,简单扫描就会找到答案
for ( i = 133; i > 0; i-- )
if ( array[i][i][i] > 0 )
the answer is array[i][i][i]
答案 1 :(得分:1)
这是一种方法,可能让我们的操作复杂性低于用户3386109的好主意。分别对三元组的每个成员进行总和枚举,并为三个枚举中的组合跟踪(索引,基数)匹配:对于三元组的每个成员,log4j
,x
和{ y
中的{1}}遍历一个单独的一维数组,表示总和最多为133,索引基数:
z
一旦我们迭代了三个一维数组,每个三元组成员一个,我们就可以追踪可能的匹配。由于在所有三个枚举中追踪(总和,基数,指数)的一致匹配的可能性很低,所以这些很少见。
例如:
(x,y,z)
正如我们所看到的,对于这个例子中的和4,在所有三个和结构(4,3)中只有一个匹配(索引,基数),然后我们可以使用相关的值追溯:
# for example, Xs enumeration only
for index, (x,y,z) in triples:
for s in [133 - x ... 0]
if sums_x[s].cardinalities.length > 0:
for cardinality in sums_x[s].cardinalities:
sums_x[s + x].by_index.add( (index,cardinality + 1) ) # this is a set of (index,cardinality) tuples
sums_x[s + x].cardinalities["cardinality + 1"].push( index ) # hash cardinality to indexes
sums_x[x].by_index.add( (index,1) )
sums_x[x].cardinalities["1"].push( index )