题目描述:
有N个骰子,同时投掷出去,向上面的数字之和为A。那么输入为N个骰子,请计算出A,和A出现的概率。概率值,小数点保留5位。
样例输入:
1
样例输出:
[[1,0.166667], [2,0.166667], [3,0.166667], [4,0.166667], [5,0.166667], [6,0.166667]]
基本思想:
动态规划,n个骰子点数和为s的种类数只与n-1个骰子的和有关。因为一个骰子有六个点数,那么第n个骰子可能出现1到6的点数。所以当第n个骰子点数为1的话,f(n,s)=f(n-1,s-1),当第n个骰子点数为2的话,f(n,s)=f(n-1,s-2),…,依次类推。在n-1个骰子的基础上,再增加一个骰子出现点数和为s的结果只有这6种情况!
那么有:
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) ,0< n<=6n
f(n,s)=0, s< n or s>6n
代码实现:
import java.util.Scanner;
public class Touzi {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int n;
Scanner sc = new Scanner(System.in);
n=sc.nextInt();
double total = Math.pow(6,n);//n个骰子一共有6的n次方个取值
System.out.print("[["+n+","+String.format("%.6f", getSum(n,n)/total)+"], ");//控制输出格式
for(int i = n+1;i<6*n;i++){
System.out.print("["+i+","+String.format("%.6f", getSum(n,i)/total)+"], ");
}
System.out.print("["+6*n+","+String.format("%.6f", getSum(n,6*n)/total)+"]]");
}
public static int getSum(int n ,int sum){
if(n<1||sum<n||sum>6*n){
return 0;
}
if(n==1){
return 1;
}
return getSum(n-1,sum-1)+getSum(n-1,sum-2)+getSum(n-1,sum-3)+getSum(n-1,sum-4)+getSum(n-1,sum-5)+getSum(n-1,sum-6);
}
}
非递归方式实现:
已知n个骰子点数和为s的种类数只与n-1个骰子的和有关,因此可以使用两个数组如a[]、b[],分别存储n-1个骰子和n个骰子点数和为s的种类数,则b[s]=a[s-1]+a[s-2]+a[s-3]+a[s-4]+a[s-5]+a[s-6]。
public class Touzi {
public static void main(String[] args) {
// TODO 自动生成的方法存根
int n;
Scanner sc = new Scanner(System.in);
n=sc.nextInt();
printProbability(n);
}
public static void printProbability(int n) {
if (n < 1)
return;
int[][] getSum = new int[2][];
getSum[0] = new int[6 * n + 1];
getSum[1] = new int[6 * n + 1];
int flag = 0;
for (int i = 1; i <= 6; i++)
getSum[0][i] = 1; //n==1时
for (int k = 2; k <= n; ++k) { //骰子数从2到n依次累增
for (int i = 0; i < k; ++i) //当有k个骰子时,点数和小于k的情况为0
getSum[1 - flag][i] = 0;
for (int sum = k; sum <= 6 * k; ++sum) { //k个骰子时,sum最小为k,最大为6*k
getSum[1 - flag][sum] = 0;
for (int j = 1; j <= sum && j <= 6; ++j)//b[s]=a[s-1]+a[s-2]+a[s-3]+a[s-4]+a[s-5]+a[s-6]
getSum[1 - flag][sum] += getSum[flag][sum - j];
}
flag = 1 - flag;
}
double total = Math.pow(6,n);//n个骰子一共有6的n次方个取值
for (int i = n; i <= 6 * n; i++) {
System.out.println(String.format("["+i+","+"%.6f", getSum[flag][i] / total)+"] ");
}
}
}