剑指 Offer 60. n个骰子的点数 + 动态规划 + 空间优化
剑指 Offer 60. n个骰子的点数
Offer_60
题目详情
题解分析
package com.walegarrett.offer;
/**
* @Author WaleGarrett
* @Date 2021/2/12 18:29
*/
/**
* 题目描述:把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
* 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
*/
import java.util.Arrays;
/**
* 动态规划:dp[i][j]表示掷n个骰子后,点数总和为j出现的次数
*/
public class Offer_60 {
public double[] dicesProbability(int n) {
int[][] dp = new int[n+1][70];
for(int i=1; i<=6; i++){
dp[1][i] = 1;
}
for(int i=2; i<=n; i++){
for(int j=i; j<=6*i; j++){
for(int k=1; k<=6 && j-k>0; k++)
dp[i][j] += dp[i-1][j-k];
}
}
double allP = Math.pow(6,n);
double[] result = new double[6*n-n+1];
for(int i=n; i<=6*n; i++){
result[i-n] = dp[n][i] * 1.0 / allP;
}
return result;
}
}
空间优化
/**
* 动态规划:空间优化
*/
class Offer_60_1 {
public double[] dicesProbability(int n) {
int[] dp = new int[70];
Arrays.fill(dp,0);
for(int i=1; i<=6; i++){
dp[i] = 1;
}
for(int i=2; i<=n; i++){
for(int j=6*i; j>=i; j--){
dp[j] = 0;//很重要
for(int k=1; k<=6 && j-k>=i-1; k++)
dp[j] += dp[j-k];
}
}
double allP = Math.pow(6,n);
double[] result = new double[6*n-n+1];
for(int i=n; i<=6*n; i++){
result[i-n] = dp[i] * 1.0 / allP;
}
return result;
}
}
题解参考:【n个骰子的点数】:详解动态规划及其优化方式
Either Excellent or Rusty