此问题取自interviewstreet.com
给定整数数组Y = y1,...,yn,我们有n个线段,这样 段i的端点是(i,0)和(i,yi)。想象一下,来自 每个片段的顶部向左侧拍摄水平光线,并拍摄此光线 当它接触另一个段或它碰到y轴时停止。我们 构造一个n个整数的数组,v1,...,vn,其中vi等于 从段顶部射出的射线长度i。我们定义V(y1,...,yn) = v1 + ... + vn。
例如,如果我们有Y = [3,2,5,3,3,4,1,2],那么v1,...,v8 = [1,1,3,1,1,3,1,2],如下图所示:
对于[1,...,n]的每个排列p,我们可以计算V(yp1,..., YPN)。如果我们选择[1,...,n]的均匀随机置换p,那么 是V(yp1,...,ypn)的期望值?
输入格式
第一行输入包含单个整数T(1 <= T <= 100)。 Ť 测试用例如下。
每个测试用例的第一行是单个整数N(1 <= N <= 50)。 下一行包含由a分隔的正整数y1,...,yN 单个空格(0
输出格式
对于每个测试用例输出预期值V(yp1,...,ypn),舍入 小数点后的两位数。
示例输入
6 3 1 2 3 3 3 3 3 3 2 2 3 4 10 2 4 4 5 10 10 10 5 10 6 1 2 3 4 5 6
示例输出
4.33 3.00 4.00 6.00 5.80 11.15
解释
案例1:我们有V(1,2,3)= 1 + 2 + 3 = 6,V(1,3,2)= 1 + 2 + 1 = 4,V(2,1,3) = 1 + 1 + 3 = 5,V(2,3,1)= 1 + 2 + 1 = 4,V(3,1,2)= 1 + 1 + 2 = 4,V(3,2,1) = 1 + 1 + 1 = 3.这些值的平均值为4.33。
案例2:无论排列是什么,V(yp1,yp2,yp3)= 1 + 1 + 1 = 3,答案是3.00。
情况3:V(y1,y2,y3)= V(y2,y1,y3)= 5,V(y1,y3,y2)= V(y2,y3,y1)= 4,V(y3,y1,y2)= V(y3,y2,y1)= 3,这些值的平均值为 4.00。
对于N = 50,问题的天真解决方案将永远运行。我相信可以通过独立计算每根棒的值来解决问题。我仍然需要知道是否有任何其他有效的方法来解决这个问题。我们在什么基础上独立计算每根棒的价值?
答案 0 :(得分:7)
我们可以通过弄清楚来解决这个问题:
如果 k th stick放在 i 位置,该棒的预期射线长度是多少。
然后可以通过将所有位置的所有棒的所有预期长度相加来解决问题。
让expected[k][i]
成为放在 i 位置的 k 棒的预期光线长度,让num[k][i][length]
为排列数 k th stick放入 i 位置,光线长度等于length
,然后
expected[k][i] = sum( num[k][i][length] * length ) / N!
如何计算num[k][i][length]
?例如,对于length=3
,请考虑以下图表:
... ... GxxxI
I
是位置,3'x'表示我们需要3支严格低于I
的支杆,而G
意味着我们需要一支至少同样高的支杆为I
。
让s_i
为小于k
小棍子的小棍数,g_i
是大于或等于k
小棍的小棍数,然后我们可以选择g_i
中的任何一个放入G
位置,我们可以选择任意length
s_i
来填充x
位置,所以我们有:
num[k][i][length] = P(s_i, length) * g_i * P(n-length-1-1)
如果I
之前的所有位置都小于I
,我们在G
中不需要更大的支持,即xxxI....
,我们有:
num[k][i][length] = P(s_i, length) * P(n-length-1)
这是一段可以解决这个问题的Python代码:
def solve(n, ys):
ret = 0
for y_i in ys:
s_i = len(filter(lambda x: x < y_i, ys))
g_i = len(filter(lambda x: x >= y_i, ys)) - 1
for i in range(n):
for length in range(1, i+1):
if length == i:
t_ret = combination[s_i][length] * factorial[length] * factorial[ n - length - 1 ]
else:
t_ret = combination[s_i][length] * factorial[length] * g_i * factorial[ n - length - 1 - 1 ]
ret += t_ret * length
return ret * 1.0 / factorial[n] + n
答案 1 :(得分:7)
这是与https://cs.stackexchange.com/questions/1076/how-to-approach-vertical-sticks-challenge相同的问题,我在那里的答案(比前面给出的更简单)是:
想象一个不同的问题:如果你必须在k
个槽中放置n
个相同高度的木棍,那么木棍之间的预期距离(以及第一个木棍和一个名义槽之间的预期距离{{ 1}},以及最后一个标记与名义广告位0
)之间的预期距离为n+1
,因为在(n+1)/(k+1)
长度中有k+1
个空白。
回到这个问题,一个特定的棒感兴趣的是多少棒(包括它自身)和高或高。如果这是n+1
,那么之前的预期差距也是k
。
因此算法只是为每个棒找到这个值并加上期望值。例如,从(n+1)/(k+1)
的高度开始,高度大于或等于的横杆数量为3,2,5,3,3,4,1,2
,因此预期为5,7,1,5,5,2,8,7
。
这很容易编程:例如R
中的一行9/6+9/8+9/2+9/6+9/6+9/3+9/9+9/8 = 15.25
给出sample output in the original problem
中的值V <- function(Y){(length(Y) + 1) * sum(1 / (rowSums(outer(Y, Y, "<=")) + 1) )}
答案 2 :(得分:1)
正确地说,我们可以为每根棍子独立解决问题。
设F(i,len)是排列数,来自标记i的光线正好是len 然后回答是
(Sum(by i,len)F(i,len)* len)/(n!)
剩下的就是计算F(i,len)。令a(i)为j的数量,即y_j <= y_i。 b(i) - 棒数,b_j> b_i。
为了获得长度为len的光线,我们需要有这样的情况。
B, l...l, O
len-1 times
O - 坚持#i。 B - 坚持更长的长度或开始。 l - 坚持高位,然后小于第i。
这给了我们两个案例:
1)B是开始,这可以P(a(i), len-1) * (b(i)+a(i)-(len-1))!
方式实现
2)B是更大的棒,这可以用P(a(i), len-1)*b(i)*(b(i)+a(i)-len)!*(n-len)
方式实现。
编辑:在(mul)中将b(i)更正为第二项,代替案例2中的(i)。