本帖最后由 j6819236 于 2016-2-17 10:45 编辑
概率公用程序直接写上去貌似有点简单,所以用递归模拟了下这个过程。
根据概率定义写的,算出事件总数sum,再算出每个人都抽不到自己的事件数signal, signal/sum就是所求概率
假设有n个人,n就代表第n个人的名字,可以用集合模拟,只要第n个人不抽到数字n也就是不抽到自己,
例如有4个人, 3,2,1,0 对应抽到的名字 0,1,2,3这就算一种情况,用递归先抽第n个人的卡片,接着n-1,直到第1个人
。但是貌似这样内存有点吃不消,有人能帮忙修改下吗,实在没办法优化。
- package com.heima;
- import java.util.ArrayList;
- import java.util.Scanner;
- /*问题要求:用键盘输入一个整数P表示参加抽奖活动的人数。
- 程序运行,输出结果为所有人都没中奖的概率。用百分号表示,四舍五入保留两位小数。
- 如输入2,结果运行输出答案应该是50.00%*/
- //总的思路,就使用集合模拟抽取过程,用集合索引n对应第n个人,集合中元素则装载着对应卡片
- public class Test10 {
- // 装载抽不到自己名字卡片的组合集合
- static ArrayList<Integer> list = new ArrayList<>();
- public static void main(String[] args) {
- Scanner sc = new Scanner(System.in);
- System.out.println("请输入参加活动人数:");
- while (true) {
- int n = sc.nextInt();
- ArrayList<Integer> arr = new ArrayList<>();
- // 模拟抽奖盒子有n张卡片,把n张卡片一一对应添加进集合arr,从0开始
- init(arr, n);
- // 是否打印所有抽不到自己名字卡片的排列组合
- System.out.println("请选择是否打印结果('1'为'是'):");
- int print = sc.nextInt();
- // 计算所有人都抽不到自己名字卡片概率并精确到指定精度
- double pro = (double) eventNotSelf(arr, print) / (double) eventSum(arr);
- StringBuffer strPro = new StringBuffer(String.valueOf(Math.round(pro * 10000)));
- System.out.println("所有人都没中奖概率:" + strPro.insert(2, ".") + "%");
- }
- }
- // 模拟把n张卡片装进抽奖盒子
- public static void init(ArrayList<Integer> arr, int n) {
- for (int i = 0; i < n; i++) {
- arr.add(i);
- }
- }
- // 计算n个人不放回地从盒子中抽1张卡片事件数总和
- public static int eventSum(ArrayList<Integer> arr) {
- int count = 0;
- // 卡片全抽完,事件数总和加1
- if (arr.size() == 1) {
- return 1;
- }
- // 模拟卡片抽取,第arr.size个人可以抽取盒子当前任意卡片,每种可能都要计算
- for (int i = 0; i < arr.size(); i++) {
- // 第arr.size个人拿出写着arr.get(i)名字卡片
- int temp = arr.get(i);
- // 盒子中去除此卡片
- arr.remove(i);
- // 第arr.size-1个人拿盒子中剩余的卡片,事件总数累加
- count = count + eventSum(arr);
- // 回到第arr.size个人,他还有可能抽写着非arr.get(i)名字卡片,所以放回arr.get(i)卡片,抽其他人名字卡片
- arr.add(i, temp);
- }
- // 返回事件总和数
- return count;
- }
- // 抽不到自己名字卡片的事件总和数,print=1打印每个人对应抽到的卡片
- public static int eventNotSelf(ArrayList<Integer> arr, int print) {
- int count = 0;
- // 模拟卡片抽取,第arr.size个人可以抽取盒子当前任意非自己名字卡片,每种可能都要计算
- for (int i = 0; i < arr.size(); i++) {
- // 第arr.size个人拿出写着arr.get(i)名字卡片
- int temp = arr.get(i);
- // 第arr.szie个人没拿到写着自己名字的卡片
- if (temp != arr.size() - 1) {
- // 装载入list
- list.add(temp);
- // 如果是最后一个人,符合事件要求,每个人都没拿到自己名字卡片,事件数总和加1
- if (arr.size() == 1) {
- // 是否打印每个人抽的的卡片
- if (print == 1)
- System.out.println(list);
- count = 1;
- // 如果不是最后一个人,则接着抽取盒子中卡片
- } else {
- // 首先从盒子中抽走arr.get(i)名字卡片
- arr.remove(i);
- // 第arr.size-1个人接着抽盒子剩余卡片,事件数总和累加
- count = count + eventNotSelf(arr, print);
- // 因为 第arr.size个人还有可能抽到非arr.get(i)名字卡片,所以放回卡片重新抽下一张
- arr.add(i, temp);
- }
- // 进入下一种情况,清除上一种情况
- list.remove(list.size() - 1);
- }
- }
- return count;
- }
- }
复制代码
|