把n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s的所有可能的值出现的概率。
你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个的概率。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
一开始的时候认为这是一到概率论的题目,但是分析以下原来是到动态规划!我们都做过上楼梯的题目;小明在1楼,每次可以上2层楼梯或者1层楼梯,请问小明上到10层楼梯的方案个数,异曲同工之妙,不过这里是每次可以上1层,2层... ...或者6层而已。这样我们按照动态分析的方式来解析该问题。
package JianZhiOffer60; import java.util.Arrays; /** * @author :dazhu * @date :Created in 2020/4/19 17:44 * @description: * @modified By: * @version: $ */ public class Main { public static void main(String[] args) { Solution solution = new Solution(); System.out.println(Arrays.toString(solution.twoSum(2))); } } class Solution { /** * * @param n 输入侄子个数 * @return 返回概率 * 状态定义:dp的行数代表当前侄子个数,列数代表当前侄子的和值,该位置存放的数代表种类数 * 状态转移:dp[n][m]代表n个侄子和为m的种类数,则有dp[n][m] = dp[n-1][m-1] +dp[n-1][m-2]+dp[n-1][m-3] +dp[n-1][m-4]+dp[n-1][m-5] +dp[n-1][m-6] * 如果超过了dp数组范围,则为0。 * 控制方向:循环dp数组从上到下,从左到右。 */ int[][] dp ; public double[] twoSum(int n) { //初始化dp数组 dp = new int[n+1][]; dp[1] = new int[]{0,1,1,1,1,1,1}; double totalKinds = Math.pow(6,n); //按照循环方向在状态转移方程下进行计算。 for(int i=2;i<n+1;i++){ //由于每一行的长度要根据当前侄子可能出现的种类数,来判断 dp[i] = new int[6*i+1]; for(int j=i;j<6*i+1;j++){ dp[i][j] = fn(i-1,j-1)+fn(i-1,j-2)+fn(i-1,j-3)+fn(i-1,j-4)+fn(i-1,j-5)+fn(i-1,j-6); } } //创建结果概率数组 double[] result = new double[5*n+1]; //在dp二维数组中计算结果数组 for(int i=0;i<5*n+1;i++){ result[i] = dp[n][i+n]/totalKinds; } return result; } /** * * @param n 当前侄子数 * @param m 当前侄子之和 * @return 当前对应的种类数 */ public int fn(int n,int m){ //如果m小于0或者超过当前行的范围,则直接返回0 if(m<0||m>=6*n+1){ return 0; } //否则返回当前位置的值即可,即当前种类数 else{ return dp[n][m]; } } }
原文:https://www.cnblogs.com/dazhu123/p/12758497.html