剑指60 n个骰子的点数

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

 

你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。

 

可以把问题分解成n-1个和1个骰子,加上这个骰子后,对于可能出现的点数x。他的值等于(x-1)+(x-2)+..+(x-6)这六个值的和,所以这也是一个递归思路的问题,但是也有很多重复计算,所以自底向上使用循环。

用两个数组分别记录上一次结果和这一次结果,每次交换。初始第一个数组需要初始1-6为1,然后每次循环时,假如是使用x个骰子,那么0-x-1就要初始化为0。

 1 class Solution {
 2 public:
 3     int maxValue=6;
 4     vector<double> twoSum(int n) {
 5         vector<double> ratio;
 6         int *probabilities[2];
 7         probabilities[0]=new int[maxValue*n+1];
 8         probabilities[1]=new int[maxValue*n+1];
 9         for(int i=0;i<maxValue*n+1;++i){
10             probabilities[0][i]=0;
11             probabilities[1][i]=0;
12         }
13         int flag=0;
14         for(int i=1;i<=maxValue;++i){
15             probabilities[flag][i]=1;
16         }
17         for(int num=2;num<=n;++num){
18             for(int i=0;i<num;++i)
19                 probabilities[1-flag][i]=0;
20             
21             for(int i=num;i<=maxValue*num;++i){
22                 probabilities[1-flag][i]=0;
23                 for(int j=1;j<=i && j<=maxValue;++j){
24                     probabilities[1-flag][i]+=probabilities[flag][i-j];
25                 }     
26             }
27             flag=1-flag;
28         }
29         double total=pow((double)maxValue,n);
30         for(int i=n;i<=maxValue*n;++i){
31             ratio.push_back(probabilities[flag][i]/total);
32         }
33         return ratio;
34     }
35 };

注意for循环中++i和i++都是效果一样的,因为for循环是在执行循环体后才执行for语句中最后一项。但是也有微小区别,i++需要申请一个空间临时存放i,然后返回计算的值;++i可以直接在原空间上执行,所以++i速度会更快。

posted @ 2020-07-07 11:52  __rookie  阅读(164)  评论(0编辑  收藏  举报