我使用Ruby,但出于这个问题的目的,它并不重要。
假设我有两种不同的资源,其数量由a
和b
表示。我可以分配d
个新资源,由于a
和b
具有相同的成本和相同的生产价值,我可以选择以最有利可图的方式分配资源。
最好这样解释:(a + j) * (b + k) = c
,其中j + k = d
。我希望通过最佳资源分配来最大化c
,同时理解两种不同类型资源的成本及其对生产的价值是相同的。所有变量都是正整数,a
和b
大于0.这是我天真的暴力方法:
def max_alloc(a, b, d)
max_j = 0
max_k = 0
max_c = 0
(0..d).each do |j|
k = d - j
c = (a + j) * (b + k)
if c > max_c
max_c = c
max_j = j
max_k = k
end
end
[max_j, max_k]
end
我希望有某种数学或算法"技巧"我不知道会让我不得不诉诸蛮力。
答案 0 :(得分:3)
你真的需要一个算法吗? 这是一个简单的最大/最小优化问题。
现在考虑等式
这是j
的函数,所以我们称之为f(j)
:
您希望找到j
,c = f(j)
最大...所以您想研究它的衍生标志
现在您可以绘制标志表
你有它!
的最大值这意味着您正在寻找的j, k
对是
对于此类值,您的最大值为c
:
def max_alloc(a, b, d)
j = (-a + b + d) / 2.0
j = j.round # round to prevent Float, explained at the end of this answer
if j < 0
j = 0 # prevent from negative values
elsif j > d
j = d # prevent from values greater than d
end
[j, d - j]
end
甚至更短
def max_alloc(a, b, d)
j = ((-a + b + d) / 2.0).round
j = [0, [j, d].min].max # make sure j is in range 0..d
[j, d - j]
end
如果您愿意,也可以使用单行内容
def max_alloc(a, b, d)
[[0, [((-a + b + d) / 2.0).round, d].min].max, d - [0, [((-a + b + d) / 2.0).round, d].min].max]
end
j < 0
和j > d
让我们从j
必须满足的界限开始:
所以j*
是:
现在,由于f(j)
始终抛物线向下打开,绝对最大值将是它的顶点,因此,正如之前发现的那样:
但如果这一点超出j
的给定范围怎么办?您必须决定选择j* = 0, k* = d
或j* = d, k* = 0
。
由于f(j)
的{{1}}严格增加且j < j*
严格减少,因此距您j > j*
越近,j*
值越大。
因此,如果f(j)
选择j* > d
,则选择j* = d
,然后选择j* < 0
。
在这里,我展示了一些情节,只是为了看到这一点:
j = 0
?正如您刚才所了解的那样j.round
是抛物线,而抛物线则具有对称轴。如果f(j)
是一个整数,那么你就完成了,否则最大化的整数值是j*
?嗯...对于最接近顶点的整数值;即,f(j)
。
注意:如果j.round
和a, b
是整数,则d
只能是整数或j*
。因此xxx.5
和f(j)
j.ceil
是相同的......您可以选择。
答案 1 :(得分:0)
对于给定的常量a
和b
,请
f(j,k) = (a + j) * (b + k)
我们希望最大化f(j,k)
符合三项要求:
j + k = d
,对于给定的常量d
j >= 0
k >= 0
我们可以替换k
(或j
)来替换k
k = d - j
这会将f
更改为:
f(j) = (a + j) * (b + d - j)
= a*(b + d) + (b + d - a)*j -j**2
现在的问题是f
最大化:
0 <= j <= d
这种不平等的第二部分来自k = d - j >= 0
。如果d = 0
,j = k = 0
是满足变量非负的要求的唯一解决方案。如果d < 0
没有可行的解决方案。应该检查这两种情况,但我会假设d > 0
。
我们首先将f
的导数设置为零并求解j
以确定f
的斜率为零的位置:
f'(j) = b + d - a - 2*j = 0
所以
j* = (b + d - a)/2
由于f
的二阶导数是
f''(j) = -2 < 0
我们知道f
是凹的,所以j*
是最大值(而不是凸起的最小值)。凸和凹函数在这里显示 1 :
考虑凹函数的图形。 j
的值在横轴上。由于j*
必须在0
和d
之间才可行(两个变量都具有非负值),所以请点a
,c
和{{图表上的1}}分别等于b
,0
和j*
。
有三种可能性:
d
,在这种情况下,这是一个可行的解决方案(从0 <= j* <= d
开始)。k = d - j* >= 0
,在这种情况下,j* < 0
的最大可行值是f
。j = 0
,在这种情况下,j* > d
的最大可行值是f
。确定j = d
的最佳值后,j
以下是一些例子。
实施例。 1:k = d - j
,a = 2
,b = 3
d = 5
由于j* = (b + d - a)/2 = (3 + 5 - 2)/2 = 3
,0 <= 3 <= 5
,j = 3
是k = 5 - 3 = 2
和j
的最佳值,k
是最佳值。
实施例。 2:f(3) = 25
,a = 6
,b = 1
d = 3
由于j* = (b + d - a)/2 = (1 + 3 - 6)/2 = -1
,-1 < 0
,j = 0
是k = 3 - 0 = 3
和j
的最佳值,k
是最佳值。
实施例。 3:f(0) = 24
,a = 2
,b = 7
d = 3
由于j* = (b + d - a)/2 = (7 + 3 - 2)/2 = 4
,4 < 3
,j = 3
是k = 3 - 3 = 0
的最佳值,j
是最佳值。
如果f(3) = 35
和j
必须是k
的最大值的整数值,我们可以假设f
,a
和{{1}是整数值。 (如果b
和d
不是,a
可以向上舍入并b
向下舍入。)现在让a
成为b
的值} j*
满足j
是最大值(但0 <= j <= d
不一定是整数)。由于f(j)
是凹的,如果j*
不是整数,f
的最佳值为j*
,如果j
,则J*.floor
。{/ {} p>
1对于所有f(j*.floor) >= f(j*.ceil)
和j*.ceil
,f
以及所有a
,b
,函数a < b
是凹的},x
,其中a <= x <= b
是具有f(x) >= g(x)
和g
属性的线性函数。