礼物
来源:互联网 发布:淘宝联盟高佣与低佣金 编辑:程序博客网 时间:2024/06/11 04:51
招聘会一共有N个人,我们公司给大家准备了一些礼物,但是我们并不知道这些人具体喜欢什么,现在库房共有m种礼物,每种礼物有Ci件,共N件。我们大致知道每个人选择某种礼物的概率,即能知道Pij(编号为i的人选择第j种礼物的概率)。现在所有人按编号依次领礼物(第1个人先领,第N个人最后领)。参加者会按照预先统计的概率告诉准备者自己想要哪一种礼物,如果该种礼物在他之前已经发放完了则他会领不到礼物,请计算出能能领到礼物的期望人数。
输入描述:
第一行包含两个整数N(1≤N≤300),M(1≤M≤100),用单个空格隔开。表示公有N个应聘者,M种礼物。第二行为M个整数,依次为Ci,第i种礼物的个数。接下来的N行,每行M个实数,一次为Pij,第i个人选择第j种礼物的概率。
输出描述:
一行输出期望人数。结果保留1位小数。
输入例子:
2 21 10.3 0.70.7 0.3
输出例子:
1.6(样例解释:共有4种选择(1,1),(1,2),(2,1),(2,2),概率分别为0.21、0.09、0.49、0.21,(1,1),(2,2)这两种选择只有1个人能拿到礼物,(1,2),(2,1)这两种选择有2个人能拿到礼物,所以期望为1*(0.21+0.21) + 2*(0.09+0.49) = 1.58,保留一位小数为1.6。)
这道题的思路是:想要求得到的礼物的人数,即发出的礼物数,即礼物总数减去剩下的礼物数
这样我们的想法就是先求出经过选择还剩多少礼物(这个的求法要比直接求送出的礼物简单些)。
某种礼物的剩余数的概率为:
0个:0个的概率 + 一个的概率*某人拿走的概率
(0 - gnum)个的概率: 当前概率*(1-拿走概率) + 比当前多一个的概率*拿走概率
gnum个:gnum个的概率 * (1 - 某人拿走的概率)
除了这个思路外,我还学到了一位小数输出格式的输出方法: System.out.println((double) (Math.round((n - leftgift)*10)/10.0));
开心~
代码如下:
import java.util.*;public class Main { public static void main(String[] args) { Scanner s = new Scanner(System.in); while(s.hasNext()) { int n = s.nextInt();//人数 int m = s.nextInt();//礼物种类数 int[] gnum = new int[m];//每类礼物个数 for(int i=0; i<m; i++) {gnum[i] = s.nextInt(); } float[][] chance = new float[n][m];//每个人选择每种礼物概率 for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { chance[i][j] = s.nextFloat(); } } double leftgift = 0;//余下礼物数 //对每类礼物进行循环 for(int i=0; i<m; i++) { if(gnum[i]==0) continue; double[] leftpro = new double[gnum[i]+1];//此类礼物不同剩余个数(0-gnum[i])的概率 leftpro[gnum[i]] = 1;//初始化为都在 //在每个人选择后对概率进行调整 for(int j=0; j<n; j++) { leftpro[0] = leftpro[0] + leftpro[1]*chance[j][i]; for(int k = 1; k<gnum[i]; k++) { leftpro[k] = leftpro[k]*(1-chance[j][i]) + leftpro[k+1]*chance[j][i]; } leftpro[gnum[i]] = leftpro[gnum[i]] * (1-chance[j][i]); } for(int j=1; j<=gnum[i]; j++) { leftgift += leftpro[j] * j; } } System.out.println((double) (Math.round((n - leftgift)*10)/10.0)); } s.close(); }}
0 0