43. 动态规划求解n个骰子的点数和出现概率(或次数)[Print sum S probability of N dices]

题目】

把N个骰子扔在地上,所有骰子朝上一面的点数之和为S。输入N,打印出S的所有可能的值出现的概率。

【分析】

典型的动态规划题目。

设n个骰子的和为s出现的次数记为f(n,s),其中n=[1-N],s=[n-6n]。

n=1, s=[1-6], f(n,s)=1;

n=[2-N], s=[n-6n], 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) = sum(f(n-1,s-t)) ,其中t=[1-6] and t<s。

最终点数之和为S出现的次数为f(N,S),概率为f(N,S)/6N。

代码】

 C++ Code 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
 

// 43_PrintSumProbabilityOfDices.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <cmath>
using namespace std;

/*
DP
f(n,s): the count of sum s of n dices, where n=[1-N],s=[n-6n]
n=1, s=[1-6], f(n,s)=1;
n=[2-N], s=[n-6n], 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) = sum(f(n-1,s-t)), where t=[1-6]&&t<s。
the final result is: f(N,S)/6^N
*/

#define MAXN 13 // N>14 f will overflow
#define MAXS 6*MAXN+1
#define FACES 6
int f[MAXN][MAXS];

void PrintSumProbabilityOfDices(int N)
{
    
if(N <= 0 || N > MAXN)
        
return;
    
// init f array
    for (int i = 0; i < MAXN; ++i)
        
for (int j = 0; j < MAXS; ++j)
            f[i][j] = 
0;

    
int n, s, t;
    
// base case n=1
    n = 1;
    
for (s = n; s <= FACES * n; ++s)
        f[n][s] = 
1;

    
// n>=2
    for (n = 2; n <= N; n++)
    {
        
for (s = n; s <= FACES * n; ++s)
        {
            
for (t = 1; t <= FACES && t < s; ++t)
            {
                f[n][s] += f[n - 
1][s - t];
            }
        }
    }

    
// print the probability or counts
    n = N;
    
double total = pow((double)FACES, n);
    
for (s = n; s <= FACES * n; ++s)
    {
        cout << s << 
"--->" << f[n][s] << endl;
        
//cout<<f[n][s]/total<<endl;
    }
}

void test_base(int n)
{
    cout << n << 
" dices." << endl;
    PrintSumProbabilityOfDices(n);
    cout << 
"---------------------- ";
}

void test_main()
{
    
for (int n = 1; n <= MAXN; n++)
        test_base(n);
}

int _tmain(int argc, _TCHAR *argv[])
{
    test_main();
    
return 0;
}

【运行结果】

win7+vs2010运行结果:

只贴出了n=1到8的结果。

1 dices.
1--->1
2--->1
3--->1
4--->1
5--->1
6--->1
----------------------
2 dices.
2--->1
3--->2
4--->3
5--->4
6--->5
7--->6
8--->5
9--->4
10--->3
11--->2
12--->1
----------------------
3 dices.
3--->1
4--->3
5--->6
6--->10
7--->15
8--->21
9--->25
10--->27
11--->27
12--->25
13--->21
14--->15
15--->10
16--->6
17--->3
18--->1
----------------------
4 dices.
4--->1
5--->4
6--->10
7--->20
8--->35
9--->56
10--->80
11--->104
12--->125
13--->140
14--->146
15--->140
16--->125
17--->104
18--->80
19--->56
20--->35
21--->20
22--->10
23--->4
24--->1
----------------------
5 dices.
5--->1
6--->5
7--->15
8--->35
9--->70
10--->126
11--->205
12--->305
13--->420
14--->540
15--->651
16--->735
17--->780
18--->780
19--->735
20--->651
21--->540
22--->420
23--->305
24--->205
25--->126
26--->70
27--->35
28--->15
29--->5
30--->1
----------------------
6 dices.
6--->1
7--->6
8--->21
9--->56
10--->126
11--->252
12--->456
13--->756
14--->1161
15--->1666
16--->2247
17--->2856
18--->3431
19--->3906
20--->4221
21--->4332
22--->4221
23--->3906
24--->3431
25--->2856
26--->2247
27--->1666
28--->1161
29--->756
30--->456
31--->252
32--->126
33--->56
34--->21
35--->6
36--->1
----------------------
7 dices.
7--->1
8--->7
9--->28
10--->84
11--->210
12--->462
13--->917
14--->1667
15--->2807
16--->4417
17--->6538
18--->9142
19--->12117
20--->15267
21--->18327
22--->20993
23--->22967
24--->24017
25--->24017
26--->22967
27--->20993
28--->18327
29--->15267
30--->12117
31--->9142
32--->6538
33--->4417
34--->2807
35--->1667
36--->917
37--->462
38--->210
39--->84
40--->28
41--->7
42--->1
----------------------
8 dices.
8--->1
9--->8
10--->36
11--->120
12--->330
13--->792
14--->1708
15--->3368
16--->6147
17--->10480
18--->16808
19--->25488
20--->36688
21--->50288
22--->65808
23--->82384
24--->98813
25--->113688
26--->125588
27--->133288
28--->135954
29--->133288
30--->125588
31--->113688
32--->98813
33--->82384
34--->65808
35--->50288
36--->36688
37--->25488
38--->16808
39--->10480
40--->6147
41--->3368
42--->1708
43--->792
44--->330
45--->120
46--->36
47--->8
48--->1
----------------------

注意,当N>14时,f数组中的若干值会溢出。

【参考】

http://zhedahht.blog.163.com/blog/static/254111742009101524946359/

http://blog.csdn.net/wuzhekai1985/article/details/6640449

个人学习笔记,欢迎拍砖!---by hellogiser

Author: hellogiser
Warning: 本文版权归作者和博客园共有,欢迎转载,但请保留此段声明,且在文章页面明显位置给出原文连接。Thanks!
Me: 如果觉得本文对你有帮助的话,那么【推荐】给大家吧,希望今后能够为大家带来更好的技术文章!敬请【关注】
原文地址:https://www.cnblogs.com/hellogiser/p/3741543.html