假设您有一个长度为n的垂直游戏板(即空格数)。而且你有一个三面骰子可以选择:前进一个,留下并返回一个。如果你低于或高于棋盘游戏空间的数量,这是一个无效的游戏。一旦你到达董事会的最后,唯一有效的举措是“留下来”。鉴于精确的掷骰数量t,是否可以通过算法计算出导致获胜游戏的独特骰子数量?
到目前为止,我已经尝试为给定数量的掷骰子生成(-1,0,1)的每个可能组合的列表,并通过列表进行排序以查看是否有任何累加到板的长度和也符合成为有效游戏的所有要求。但是对于20岁以上的骰子来说这是不切实际的。
例如: t = 1,n = 2;输出= 1 t = 3,n = 2;输出= 3
答案 0 :(得分:6)
您可以使用动态编程方法。重复的草图是:
M(0, 1) = 1
M(t, n) = T(t-1, n-1) + T(t-1, n) + T(t-1, n+1)
当然,您必须考虑边界情况(例如离开电路板或不允许退出电路板的末端,但很容易编码)。
这是一些Python代码:
def solve(N, T):
M, M2 = [0]*N, [0]*N
M[0] = 1
for i in xrange(T):
M, M2 = M2, M
for j in xrange(N):
M[j] = (j>0 and M2[j-1]) + M2[j] + (j+1<N-1 and M2[j+1])
return M[N-1]
print solve(3, 2) #1
print solve(2, 1) #1
print solve(2, 3) #3
print solve(5, 20) #19535230
奖励:花哨的“单行”与列表compreehension并减少
def solve(N, T):
return reduce(
lambda M, _: [(j>0 and M[j-1]) + M[j] + (j<N-2 and M[j+1]) for j in xrange(N)],
xrange(T), [1]+[0]*N)[-1]
答案 1 :(得分:4)
如果M[i, j]
N
,则N
M[i, j] = 1
|i-j| <= 1
0
M[N, N-1] = 0
1
i
保持“j
的规则”
此矩阵计算从t
位置到M
位置的长度为t
的路径。
要查找长度为M^t[1, N]
的路径,只需将>>> import numpy
>>> M = numpy.matrix('1 1 0 0 0;1 1 1 0 0; 0 1 1 1 0; 0 0 1 1 1; 0 0 0 0 1')
>>> M
matrix([[1, 1, 0, 0, 0],
[1, 1, 1, 0, 0],
[0, 1, 1, 1, 0],
[0, 0, 1, 1, 1],
[0, 0, 0, 0, 1]])
>>> M ** 20
matrix([[31628466, 51170460, 51163695, 31617520, 19535230],
[51170460, 82792161, 82787980, 51163695, 31617520],
[51163695, 82787980, 82792161, 51170460, 31628465],
[31617520, 51163695, 51170460, 31628466, 19552940],
[ 0, 0, 0, 0, 1]])
提升为M^20[1, 5]
'次幂。这可以通过线性代数包有效地完成。
可以读取解决方案:<'a>
。
例如,在交互式Python会话中计算大小为5的板上的长度为20的路径:
<T>
所以在一块5号的电路板上,从头到尾有fn subslice<'a, T>(s: &'a [T], until: u32) -> &'a [T] { \\'
&s[..until as usize]
}
或19535230条长度为20的路径。
答案 2 :(得分:0)
尝试回溯算法。递归&#34;潜水&#34;进入深度t
并仅继续使用仍可能导致有效状态的骰子值。通过传递剩余预算&#34;周围。
例如,n=10, t=20
,当您达到20的深度10并且预算仍然是10(=向前和向后的步骤似乎取消)时,下一个递归步骤直到深度t
将停止0
和-1
种可能性,因为它们最终无法生成有效状态。
对于这种情况的回溯算法仍然非常沉重(指数),但比首先用所有可能性吹出气泡然后过滤更好。
答案 3 :(得分:0)
由于可以在任何地方添加零,我们将通过(-1)的不同排列来增加这些可能性:
X (space 1) X (space 2) X (space 3) X (space 4) X
( - 1)只能出现在空格1,2或3中,而不能出现在空格4中。我得到help的数学重复,它计算放置减去的方法的数量,而不会向后跳过。
JavaScript代码:
function C(n,k){if(k==0||n==k)return 1;var p=n;for(var i=2;i<=k;i++)p*=(n+1-i)/i;return p}
function sumCoefficients(arr,cs){
var s = 0, i = -1;
while (arr[++i]){
s += cs[i] * arr[i];
}
return s;
}
function f(n,t){
var numMinusOnes = (t - (n-1)) >> 1
result = C(t,n-1),
numPlaces = n - 2,
cs = [];
for (var i=1; numPlaces-i>=i-1; i++){
cs.push(-Math.pow(-1,i) * C(numPlaces + 1 - i,i));
}
var As = new Array(cs.length),
An;
As[0] = 1;
for (var m=1; m<=numMinusOnes; m++){
var zeros = t - (n-1) - 2*m;
An = sumCoefficients(As,cs);
As.unshift(An);
As.pop();
result += An * C(zeros + 2*m + n-1,zeros);
}
return result;
}
输出:
console.log(f(5,20))
19535230