最近我在做项目时遇到了一个难以解决的问题。我想问你们一个解决它的解决方案/算法,因为我真的很难想到这样做的聪明主意。
我有任意数量的花车:
和一个整数:
我需要将整数 I 划分为浮点数,就像我分发不可分割的东西一样。所以基本上这个比例在某种意义上必须保持,因为最大的浮动必须得到最大的整数。一个好的比喻就好像我在分割那些无法分割的股票。
如果第一个投资者拥有0.6%的股票而第二个投资者拥有0.4个股票,那么给定1个股票进行拆分,我会将其交给第一个(100%0%)。如果有2只股票,我会给第一只和第一种(50%50%)。请注意,我总是希望拆分尽可能成比例(接近60%40%)。
问题本身并没有非常明确的定义,但是应该知道应该发生什么,不应该发生什么。一些容易出现在我脑海中的例子是:
如果: f1 = 0.4,f2 = 0.3,f3 = 0.3,I = 1 那么我需要 f1-result = 1,f2-result = 0,f3-结果= 0 ,
如果: f1 = 0.4,f2 = 0.4,f3 = 0.2,I = 1 那么我需要 f1-result = 1,f2-result = 0,f3- result = 0 或 f1-result = 0,f2-result = 1,f3-result = 0
如果: f1 = 0.6,f2 = 0.25,f3 = 0.15,I = 5 那么我需要 f1-result = 3,f2-result = 2,f3-结果= 1 。
答案 0 :(得分:2)
至少在最初阶段我是如何接近它的。
每个桶都有所需的量。这是基于它们的浮点值,并且所有浮点值总和为1。
所以,仔细阅读"对象"一个接一个地分发。要确定哪个桶获得它,您需要找到低于所需数量的存储桶的最大差异(如果在所需级别下有多个等于它们,则选择第一个)。这是"最不快乐的"桶。
然后将该对象分发到该存储桶,调整数字并移至下一个对象。这意味着一个物体总是以这样的方式分布,使不幸的水桶的生活更好一点(好悲伤,这听起来像我是一个社会工作者)。
举例来说,让我们开始根据上述算法将对象分配给三个桶(分别需要50%,30%和20%)。
括号中的第二个数字是每个桶与其所需百分比的偏差,因此,在每个阶段,我们选择最低于所需水平的桶,最不快(由*
表示):
BucketA (50%) BucketB (30%) BucketC (20%)
------------- ------------- -------------
0 (0%,-50*) 0 (0%,-30) 0 (0%,-20)
1 (100%,+50) 0 (0%,-30*) 0 (0%,-20)
1 (50%,+0) 1 (50%,+20) 0 (0%,-20*)
1 (33%,-17*) 1 (33%,+3) 1 (33%,+13)
2 (50%,+0) 1 (25%,-5*) 1 (25%,+5)
2 (40%,-10*) 2 (40%,+10) 1 (20%,+0)
3 (50%,+0) 2 (33%,+3) 1 (17%,-3*)
3 (43%,-7*) 2 (29%,-1) 2 (29%,+9)
4 (50%,+0) 2 (25%,-5*) 2 (25%,+5)
4 (44%,-6*) 3 (33%,+3) 2 (22%,+2)
5 (50%,+0) 3 (30%,+0) 2 (20%,+0)
请注意,初始条件包含0%
处的所有存储桶,即使它技术上不正确(它可以很容易地被视为100%
甚至{{ {1}}基于计算的未定义的零除零性质。但是,这是确保初始分配到需要最高百分比的存储桶的好方法,之后百分比变得很明确。
从上面的表格中可以看出,物体的分布最终会导致预期的结果。
而且,如果您想要一些代码,您可以使用它来实现这一点(让我们面对它,不会想要那个?),请参阅以下内容Python程序:
3.14159%
输出:
desiredPct = [50, 30, 20]
bucket = [0, 0, 0]
count = 0
# Allocate first item specially so no concern with div-by-zero.
idx = desiredPct.index(max(desiredPct))
happy_min = -desiredPct[idx]
bucket[idx] += 1
count += 1
actualPct = [x * 100 / count for x in bucket]
print "Unhappiest %6.2f @ %d, want %s%%, have %s (%s%%)" % (happy_min, idx, desiredPct, bucket, actualPct)
# Allocate all others in loop.
for i in range(99):
# Get most disadvantaged bucket.
idx = 0
happy_min = bucket[idx] * 100 / sum(bucket) - desiredPct[idx]
for j in range(1, len(bucket)):
happy = bucket[j] * 100 / sum(bucket) - desiredPct[j]
if happy < happy_min:
idx = j
happy_min = happy
bucket[idx] += 1
count += 1
actualPct = [x * 100 / count for x in bucket]
print "Unhappiest %6.2f @ %d, want %s%%, have %s (%s%%)" % (happy_min, idx, desiredPct, bucket, actualPct)
这也表明,一旦你第一次获得所需的结果,对象的分布往往会接近你想要的。
答案 1 :(得分:1)
投资者j
应至少获得floor(fj*I)
份。要分配超额份额,首先确定其数量(x = I - sum(floor(fj*I) for all j)
),然后选择分数数组x
中的fj*I - floor(fj*I)
最大元素。比这更大一点的每个人都可以获得更多份额;具有这一分数的人可以根据需要获得一个或零,以使总数有效。
运行时间为O(n)
,其中n
为投资者数量。
答案 2 :(得分:0)
您使用 f1 + f2 + .... + fn = 1 启动了问题,但最后只提到了三个浮点数。 解决这个问题的简单方法是将最小的 fi 乘以10(10 ^ p)的幂,以获得整数值。你从整数(10 ^ p)中减去要分配的金额,以计算出从每个浮点数到达分配金额需要多少钱,假设你带来的额外金额最多为(10 ^ p)每个人获得其共享时间(10 ^ p)。 您通过重复计划执行此操作,首先您从每个浮动收回超过分配金额的金额。在下一次迭代中,您从每个浮点数中收集一个单位,按升序排序,但您应该考虑不要为负数。测试你是否在每次扣除后获得全部金额。
所以举例说明 f1 = 0.6,f2 = 0.25,f3 = 015,I = 5。 用f(i,j)声明浮点数矩阵f,其中i = 3且j = 2,它是两列和三行的矩阵。将浮点数存储在第一列中并对矩阵进行升序排序。访问矩阵f(1,1)的第一个元素得到0.15。 将其转换为整数,因为It = f(1,1)*(10 ^(小数位数(f(1,1))),我们得到It = 0.15 *(10 ^ 2)。即它= 15。矩阵第二列,带整数
f(1,2)=15
f(2,2)=25
f(3,2)=60
现在我必须收回10 ^ 2-5 = 95的金额。设置它= 95。第一轮,每个拥有超过5的人都会给予超额回报。所以我得到以下内容(为了简化示例,我正在跳过测试f(i,2)&gt; 5)
10 = f(1,2)-5; f(1,2)=f(1,2)-10
20 = f(2,2)-5; f(2,2)=f(2,2)-20
55 = f(3,2)-5; f(3,2)=f(3,2)-55
直到知道我声称回复 10 + 20 + 55 = 85 。我必须去另一个十。现在每个人有五个。这是三次迭代。循环的第一次第二次和第三次运行将从每个单位获得一个单位。 现在我回到了94 我仍然需要一个单位,这将是从f(2,1)和循环声明的将离开,因为我已达到我的95单位。在三次迭代和第四次迭代的一步之后,我的最终矩阵是
f(1,2)=1,
f(2,2)=2,
f(2,3)=2.
其中显而易见的原因总计为5 迭代算法很简单。它迭代f(i,2)。它测试f(i,s)> 0,然后它从f(i,2)中扣除一个单位;将此单位添加到目前为止要求的金额,并测试金额是否等于要返还的总金额。如果是真的话会破坏循环。