首页 > 试题广场 >

招聘会小礼品

[编程题]招聘会小礼品
  • 热度指数:1074 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
小摩召开了一场招聘会,招聘会现场一共有N个人,Mobike公司给大家准备了一些小礼品。但是我们并不知道每个人具体喜欢什么,
现在库房共有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位小数。
示例1

输入

2 2
1 1
0.3 0.7
0.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。)
# Algorithm: # the problem of calcu the number of prizes obtained is equal to the problem of calcu the number # of prizes left behind, that is, getPrize = N - leftPrize. # So, we can easily calcu the prob (p_k) of the prize j (j: 1~M) left with k (k: 1~C[j]) items  # after the selecting process of i (i: 1~N) interviewees in each iteration, # that is, p_k' = p_k*(1-P[i][j]) + p_(k+1)*P[i][j] def prizeGetFunc(N,M,C,P):     """"     Parameters     ----------     N :   number of interviewees     M :   kinds of the gifts     C :   number of each gift     P :   preferential matrix     """     leftPrize = 0     # initiate the number of prizes left     for j in range(M):         prizeLeftPro = [0]*C[j]+[1]  # initialize the left prob of each prize (from 0 to C[j])         for i in range(N):             prizeLeftPro[0] += prizeLeftPro[1] * P[i][j] # left 0, prizes of kind i are all given             for k in range(C[j]):                 prizeLeftPro[k] = prizeLeftPro[k]*(1-P[i][j]) + prizeLeftPro[k+1]*P[i][j] # update the p_k             prizeLeftPro[C[j]] = prizeLeftPro[C[j]]*(1-P[i][j])         for k in range(1,C[j]+1):             leftPrize += prizeLeftPro[k]*k # calculate the expected number of prizes left     getPrize = round(N-leftPrize,1)     return getPrize
N = int(raw_input())     M = int(raw_input())     C = map(int,raw_input().split())     P = [[map(int,raw_input().split())] for i in range(N)]     getPrize = prizeGetFunc(N,M,C,P)     print getPrize        

编辑于 2018-08-01 20:54:19 回复(1)
#include <ios>
#include <iostream>
#include <vector>
using namespace std;

int main()
{
    int M, N;
    cin >> N >> M;
    // N✖️M 矩阵
    vector<vector<float>> P(N, vector<float>(M));
    vector<int> gifts(M);
    for (int i = 0; i < M; i++)
    {
        cin >> gifts[i];
    }

    for (int i = 0; i < N; i++)
    {
        for (int j = 0; j < M; j++)
        {
            cin >> P[i][j];
        }
    }
    // dp 是M✖️N的矩阵, dp[i][j]表示第i种物品被前不被前j个人选中的概率
    vector<float> obj_pos(M);
    // 对每个物品单独处理
    for (int i = 0; i < M; i++)
    {
        auto *dp = new vector<float>(gifts[i] + 1, 0.0);
        (*dp)[0] = 1 - P[0][i];
        (*dp)[1] = P[0][i];
        for (int j = 1; j < N; j++)
        {
            for (int k = min(gifts[i],j); k >= 1; k--)
            {
                if (k == gifts[i])
                {

                    (*dp)[k] = (*dp)[k] + (*dp)[k - 1] * P[j][i];
                }
                else
                {
                    (*dp)[k] = (*dp)[k] * (1 - P[j][i]) + (*dp)[k - 1] * P[j][i];
                }
            }
            (*dp)[0] = (*dp)[0] * (1 - P[j][i]);
        }
        
        for (int k = 0; k <= gifts[i]; k++)
        {
            obj_pos[i] += k * (*dp)[k];
        }
        delete dp;
    }
    float sum = 0;
    for (auto e : obj_pos)
    {
        sum += e;
    }
    cout << fixed << setprecision(1) << sum << endl;
}

发表于 2025-02-16 13:27:41 回复(0)
跟题解不一样的正向版本
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        int M = in.nextInt();
        int[] counts = new int[M];
        for (int i = 0; i < M; i++) {
            counts[i] = in.nextInt();
        }
        float[][] p = new float[N][M];
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                p[i][j] = in.nextFloat();
            }
        }

        float[] p_select = new float[N + 1];
        float totalExpected = 0;  // 累加能领到小礼品的期望人数

        for (int i = 0; i < M; i++) {
            Arrays.fill(p_select, 0.0f);
            p_select[0] = 1.0f;  // 初始时0个礼物被选

            // 对每个参与者更新礼品 i 的选择概率
            for (int j = 0; j < N; j++) {
                for(int k = counts[i]; k>=0; k--){
                    if(k==0){
                        p_select[k] = p_select[k]*(1-p[j][i]);
                    }else if(k<counts[i]){
                        p_select[k] = p_select[k]*(1-p[j][i]) + p_select[k-1]*p[j][i];
                    }else{
                        p_select[k] = p_select[k] + p_select[k-1]*p[j][i];
                    }
                }              
            }

            for(int k=1; k<=counts[i]; k++){
                    totalExpected += k*p_select[k];
            }
        }
        System.out.printf("%.1f",totalExpected);
    }
}


发表于 2025-02-21 22:11:18 回复(0)

import java.math.BigDecimal;
import java.util.Scanner;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static double exp=0;
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        int N = in.nextInt();
        int M = in.nextInt();
        int[] num = new int[M];
        double[][] pros = new double[N][M];
        for(int i=0;i<M;i++){
            num[i] = in.nextInt();
        }

        for(int i=0;i<N;i++){
            for(int j=0;j<M;j++){
                pros[i][j] = in.nextDouble();
            }
        }
        travel(pros,num,0,0,1,M,N);

        BigDecimal bigDecimal = new BigDecimal(exp);
        double ans = bigDecimal.setScale(1, BigDecimal.ROUND_HALF_UP).doubleValue();
        System.out.println(ans);
    }

    public static void travel(double[][] pros,int[] num,int index,int total, double pro,int M,int N){
        if (index==N){
            exp += total*pro;
            return;
        }

        for(int i=0;i<M;i++){
            if(num[i]>0){
                total++;
            }
            num[i]--;
            pro *= pros[index][i];
            travel(pros,num,index+1,total,pro,M, N);
            pro /= pros[index][i];
            num[i]++;
            if(num[i]>0){
                total--;
            }

        }
    }
}
发表于 2024-08-28 16:48:04 回复(0)
//问了kimi给的方法,没有通过。
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = scanner.nextInt(); // 应聘者的数量
        int M = scanner.nextInt(); // 小礼品的种类数

        int[] C = new int[M]; // 小礼品的数量
        double[][] P = new double[N][M]; // 选择小礼品的概率矩阵

        // 读取每种小礼品的数量
        for (int i = 0; i < M; i++) {
            C[i] = scanner.nextInt();
        }

        // 读取每个人选择每种小礼品的概率
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < M; j++) {
                P[i][j] = scanner.nextDouble();
            }
        }

        double expectedCount = calculateExpectedGifts(N, M, C, P);
        System.out.printf("%.1f\n", expectedCount); // 输出期望人数,保留一位小数
    }

    private static double calculateExpectedGifts(int N, int M, int[] C, double[][] P) {
        double expectedCount = 0;
        double[] giftsLeft=new double[M];// 当前剩余的小礼品数量
        for (int i = 0; i < M; i++) {
            giftsLeft[i] = C[i]; // 将整数数组C转换为double数组
        }
        for (int i = 0; i < N; i++) {
            double[] giftsLeftNext = Arrays.copyOf(giftsLeft, M);
            for (int j = 0; j < M; j++) {
                // 更新每种小礼品剩余的数量
                giftsLeftNext[j] -= P[i][j] * giftsLeft[j];
            }
            giftsLeft = giftsLeftNext;

            // 计算当前人能领到小礼品的期望数量
            for (int j = 0; j < M; j++) {
                expectedCount += Math.max(0, 1 - giftsLeft[j] / (C[j] + 1e-5));
            }
        }

        return expectedCount;
    }
}

发表于 2024-08-11 10:54:19 回复(0)
import itertools
# 能实现,但是耗费时间太多,先占个坑等想出来了再补充吧- -
nm = input().split()
n, m = int(nm[0]), int(nm[1])
gifts_types = list(range(m))
gifts_num = list(map(int, input().split()))
prob_gifts = []
total_exp = 0
for _ in range(n):
    prob_gifts.append(list(map(float, input().split())))
for choice in itertools.product(gifts_types, repeat=n):
    temp_dict = {}
    prob_temp = 1
    for j in range(n):
        if choice[j] not in temp_dict.keys():
            temp_dict[choice[j]] = choice.count(choice[j])
        prob_temp *= prob_gifts[j][choice[j]]
    if prob_temp > 0:
        num_temp = 0
        for k in temp_dict.keys():
            num_temp += min(temp_dict[k], gifts_num[k])
    else:
        continue
    total_exp += prob_temp * num_temp
print("%.1f" % total_exp)

发表于 2018-10-04 22:59:12 回复(0)