我看到了关于jobcup的问题,但我没有得到我想要的答案。我自己写了一个答案,希望您对我对时间复杂度的分析发表评论,并对算法和代码进行评论。或者你可以在时间方面提供更好的算法。感谢。
你被给予d> 0个公平骰子,n> 0" sides",写一个函数,返回骰子结果频率的直方图。
例如,对于2个骰子,每个骰子有3个边,结果是:
(1, 1) -> 2
(1, 2) -> 3
(1, 3) -> 4
(2, 1) -> 3
(2, 2) -> 4
(2, 3) -> 5
(3, 1) -> 4
(3, 2) -> 5
(3, 3) -> 6
该函数应返回:
2: 1
3: 2
4: 3
5: 2
6: 1
(我的溶胶)。如果使用强力深度优先搜索,则时间复杂度为O(n ^ d)。但是,您可以使用DP思想来解决此问题。例如,d = 3且n = 3。计算d == 2时可以使用d == 1的结果:
d==1
num #
1 1
2 1
3 1
d==2
first roll second roll is 1
num # num #
1 1 2 1
2 1 -> 3 1
3 1 4 1
first roll second roll is 2
num # num #
1 1 3 1
2 1 -> 4 1
3 1 5 1
first roll second roll is 3
num # num #
1 1 4 1
2 1 -> 5 1
3 1 6 1
因此,
second roll
num #
2 1
3 2
4 3
5 2
6 1
此DP算法的时间复杂度为
SUM_i(1:d) {n*[n(d-1)-(d-1)+1]} ~ O(n^2*d^2)
~~~~~~~~~~~~~~~ <--eg. d=2, n=3, range from 2~6
代码用C ++编写如下
vector<pair<int,long long>> diceHisto(int numSide, int numDice) {
int n = numSide*numDice;
vector<long long> cur(n+1,0), nxt(n+1,0);
for(int i=1; i<=numSide; i++) cur[i]=1;
for(int i=2; i<=numDice; i++) {
int start = i-1, end = (i-1)*numSide; // range of previous sum of rolls
//cout<<"start="<<start<<" end="<<end<<endl;
for(int j=1; j<=numSide; j++) {
for(int k=start; k<=end; k++)
nxt[k+j] += cur[k];
}
swap(cur,nxt);
for(int j=start; j<=end; j++) nxt[j]=0;
}
vector<pair<int,long long>> result;
for(int i=numDice; i<=numSide*numDice; i++)
result.push_back({i,cur[i]});
return result;
}
答案 0 :(得分:1)
你可以在O(n * d ^ 2)中完成。首先,请注意,n边骰子的生成函数是p(n)= x + x ^ 2 + x ^ 3 + ... + x ^ n,并且d抛出的分布具有生成函数p(n )^ d。将多项式表示为数组,需要O(nd)系数,并且通过保持滚动总和,可以在O(nd)时间内单次通过p(n)。
这是一些实现此功能的python代码。它有一个非显而易见的优化:它从每个p(n)中抛出一个因子x(或者等效地,它将骰子视为具有面0,1,2,...,n-1而不是1,2, 3,...,n)这就是为什么在显示分布时加入d的原因。
def dice(n, d):
r = [1] + [0] * (n-1) * d
nr = [0] * len(r)
for k in xrange(d):
t = 0
for i in xrange(len(r)):
t += r[i]
if i >= n:
t -= r[i-n]
nr[i] = t
r, nr = nr, r
return r
def show_dist(n, d):
for i, k in enumerate(dice(n, d)):
if k: print i + d, k
show_dist(6, 3)
时间和空间的复杂性很容易看出:有d和(n-1)* d迭代的嵌套循环因此时间复杂度为O(nd ^ 2),并且有两个大小为O(nd)且没有其他分配的数组,因此空间复杂度为O(nd)。
答案 1 :(得分:0)
以防万一,这里是Python中使用the OpenTurns platform的简单示例。
import openturns as ot
d = 2 # number of dice
n = 6 # number of sides per die
# possible values
dice_distribution = ot.UserDefined([[i] for i in range(1, n + 1)])
# create the sum distribution d times the sum
sum_distribution = sum([dice_distribution] * d)
就是这样!
print(sum_distribution)
将向您显示所有可能的值及其对应的概率:
>>> UserDefined(
{x = [2], p = 0.0277778},
{x = [3], p = 0.0555556},
{x = [4], p = 0.0833333},
{x = [5], p = 0.111111},
{x = [6], p = 0.138889},
{x = [7], p = 0.166667},
{x = [8], p = 0.138889},
{x = [9], p = 0.111111},
{x = [10], p = 0.0833333},
{x = [11], p = 0.0555556},
{x = [12], p = 0.0277778}
)
您还可以绘制概率分布函数:
sum_distribution.drawPDF()