解题思路:
第一步,确定问题解的表达式。可将f(n, s) 表示n个骰子点数的和为s的排列情况总数。
第二步,确定状态转移方程。n个骰子点数和为s的种类数只与n-1个骰子的和有关。因为一个骰子有六个点数,那么第n个骰子可能出现1到6的点数。所以第n个骰子点数为1的话,f(n,s)=f(n-1,s-1),当第n个骰子点数为2的话,f(n,s)=f(n-1,s-2),…,依次类推。在n-1个骰子的基础上,再增加一个骰子出现点数和为s的结果只有这6种情况!那么有:
f(n,s)=f(n-1,s-1)+f(n-1,s-2)+f(n-1,s-3)+f(n-1,s-4)+f(n-1,s-5)+f(n-1,s-6)
f(n,s)=0, s< n or s>6n
递归解决
/**
* 递归处理n个骰子问题
* @param n
*/
public void getAllPro(int n) {
for(int i=n;i<=n*6;i++) {
//输出概率
// System.out.println("("+n+","+i+")--"+getEachPro(n,i)/Math.pow(6, n));
System.out.println("("+n+","+i+")--"+getEachPro(n,i));
}
}
public double getEachPro(int n, int sum) {
if(n<1 || sum<n || sum >6*n) {
return 0;
}
if(n==1) {
return 1;
}
return getEachPro(n-1, sum-1)+getEachPro(n-1, sum-2)+
getEachPro(n-1, sum-3)+getEachPro(n-1, sum-4)+
getEachPro(n-1, sum-5)+getEachPro(n-1, sum-6);
}
动态规划(迭代)
1、num=3实例(通过递归改为迭代)
/**
* dp version
*
*/
public int[][] getAllProDp(int n) {
int[][] res = new int[n+1][6*n+1];
for(int i=0;i<res.length;i++) {
for(int j=0;j<res[0].length;j++) {
if(i==0) {
//0 line
res[i][j] = 0;continue;
}
if (i==1) {
//1 line
res[i][j] = (j<7 && j>0) ? 1: 0;//摇出{1,2,3,,4,5,6}次数全部为1
continue;
}
if(i!=1){
if(j>6*i || j<i) {
res[i][j] = 0;
}else {
//current line get by (current-1) and up to 6 times
int temp = j;
int k=0;
while(true){
res[i][j] += res[i-1][temp-1];
temp--;
k++;
if(temp == i-1 || k==6){
break;
}
}
}
}
}
}
return res;
}
结果
(3,3)--1.0
(3,4)--3.0
(3,5)--6.0
(3,6)--10.0
(3,7)--15.0
(3,8)--21.0
(3,9)--25.0
(3,10)--27.0
(3,11)--27.0
(3,12)--25.0
(3,13)--21.0
(3,14)--15.0
(3,15)--10.0
(3,16)--6.0
(3,17)--3.0
(3,18)--1.0