题目:把n个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入n,打印出S的所有可能的值出现的概率。
声明思想非原创!只因动态规划思想的使用很好,记下!
分析:动态规划就是分阶段考虑问题,给出变量,找出相邻阶段间的关系。具体定义给忘了。
1.现在变量有:骰子个数,点数和。当有k个骰子,点数和为n时,出现次数记为f(k,n)。那与k-1个骰子阶段之间的关系是怎样的?
2.当我有k-1个骰子时,再增加一个骰子,这个骰子的点数只可能为1、2、3、4、5或6。那k个骰子得到点数和为n的情况有:
(k-1,n-1):第k个骰子投了点数1
(k-1,n-2):第k个骰子投了点数2
(k-1,n-3):第k个骰子投了点数3
….
(k-1,n-6):第k个骰子投了点数6
在k-1个骰子的基础上,再增加一个骰子出现点数和为n的结果只有这6种情况!
所以:f(k,n)=f(k-1,n-1)+f(k-1,n-2)+f(k-1,n-3)+f(k-1,n-4)+f(k-1,n-5)+f(k-1,n-6)
3.有1个骰子,f(1,1)=f(1,2)=f(1,3)=f(1,4)=f(1,5)=f(1,6)=1。
int findSum(int n)
{
// alloc 2-d array to store result,
// the index of array is the sum,
// the element value is times of the sum,
// for example, if there are two dices, the array is like below'
// 0 1 2 3 4 5 6 7 8 9 10 11 12 ...
//a[1][] : 0 1 1 1 1 1 1 // there is only one dice
//a[2][] : 0 0 1 2 3 4 5 6 5 4 3 2 1 // there are two dices
int *array[n + 1];
//alloc array
int j = 0;
int i = 0;
for (i = 0; i <= n; i++) {
array[i] = new int[6*i + 1];
}
// initialise the array
for (i = 0; i <= n; i++) {
for (j = 0; j <= 6*i; j++) {
array[i][j] = 0;
}
}
//calculate
for (i = 1; i <= n; i++) {
for (j = i; j <= 6*i; j++) {
if (i == 1 || j == i || j == 6*i) {
array[i][j] = 1;
} else {
int k;
for (k = 1; k <=6; k++) {
if ((j-k) >= (i -1) && (j-k) <= 6*(i-1))
array[i][j] += array[i-1][j-k];
}
}
}
}
for (i = 1; i<= n; i++) {
cout << "a[" << i <<"]: ";
for (j = i; j <= 6*i; j++) {
cout << array[i][j] << " ";
}
cout<<endl;
}
return 0;
}