你会得到许多骰子,每个骰子都有许多面孔。你滚动所有的骰子并记下你掷出每个骰子所得到的所有投掷的总和。如果你得到一笔> = x,你就赢了,否则就输了。找出你获胜的概率。
我想过生成1到m(大小为n)的所有组合,并且只保留那些总和大于x的组合。方式总数是m ^ n
之后它只是两者的分歧。
有更好的方法吗?
答案 0 :(得分:7)
[编辑:正如jpalacek所说,时间复杂性是错误的 - 我现在已经解决了这个问题。]
您可以通过动态编程更有效地解决这个问题,首先将其更改为问题:
我可以从n个骰子中获得至少x的多少种方式?
将其表示为f(x,n)。那一定是那个
f(x,n)= sum(f(x-i,n-1))对于所有1&lt; = i <= m。
即。如果第一个骰子有1个,剩下的n - 1个骰子必须加起来至少为x - 1;如果第一个骰子有2个,剩下的n - 1个骰子必须加起来至少为x - 2;等等。
总和中有m个术语,所以如果你memoise这个函数,它将是O(m ^ 2 * n ^ 2),因为它最多需要做这个求和工作(m * n)* n次(即每个唯一的函数输入集合一次,假设第一个参数x <= m * n)。
作为获得概率的最后一步,只需将f(x,n)的结果除以可能结果的总数,即m ^ n。
答案 1 :(得分:4)
只是为了加上@ j_random_hacker的基本正确答案,当你注意到
时,你可以更快f(x,n)= f(x-1,n)-f(x-m-1,n-1)+ f(x-1,n-1)如果x> m + 1
这样,您只需花费O(1)
时间计算每个f
值。
答案 2 :(得分:1)
//传递curFace值将禁止重复组合
//对于3个骰子 - 和8 - 2 4 2和2 2 4是相同的组合 - 所以应该算作一个
int sums(int totSum,int noDices,int mFaces,int curFace,HashMap<String,Integer> map)
{
int count=0;
if (noDices<=0 || totSum<=0)
return 0;
if (noDices==1)
{
if (totSum>=1 & totSum<=mFaces)
return 1;
else
return 0;
}
if (map.containsKey(noDices+"-"+totSum))
return map.get(noDices+"-"+totSum);
for (int i=curFace;i<=mFaces;i++)
{
count+=sums(totSum-i,noDices-1,mFaces,i,map);
}
map.put(noDices+"-" +totSum,count);
return count;
}