美团笔试题-最大期望分数

  小美即将进行期末考试!小美现在盘算了一下,一共有n道试题,对于第 i 道试题,小美有着pi的概率做对,
  获得ai的分值,另外(1-pi)的概率做错,获得0分。小美的总分即是每道题获得的分数之和。小美不甘于此!
  她决定突击复习,因为时间有限,她最多复习m道试题,使得复习后的试题正确率提升到100%。小美想知道,如果她以最佳方式进行复习,能获得的期望总分最大是多少。
输入描述
  第一行两个正整数n和m,表示总试题数和最多复习试题数。
 
  接下来一行n个整数,分别为p1 p2...pn,表示小美有pi%的概率,即pi=pi/100的概率做对第i个题。(注意,这里为了简单起见,将概率pi扩张100倍成为整数pi方便输入)
 
  接下来一行n个整数,分别表示a1 a2...an,分别表示第 i 个题做对的分值。
 
  数字间两两有空格隔开,对于所有数据,1≤m≤n≤50000,0≤pi≤100,1≤ai≤1000
 
  输出描述
  输出一行一个恰好两位的小数,表示能获得的最大期望总分。(如果答案为10应输出10.00,2.5应输出2.50)
 
 
 样例输入
 2 1
 89 38
 445 754
 样例输出
 1150.05
 
  提示
  如果都不复习,小美总分的期望为89%*445+38%*754=682.57
 
  如果复习第一道题,小美总分的期望为100%*445+38%*754=731.52
 
  如果复习第二道题,小美总分的期望为89%*445+100%*754=1150.05
 
  所以选择复习第二道题,这样能获得最大期望总分1150.05
 
  根据每题复习后的收益进行排序即可


方法1:

 首先可以确定的是获得最大分数的前提是 m次复习都使用 。因为用了就是100%获得分数 ;那么我们要做的就是 找出该复习哪m门课。 使得效益最好直接的方式: 暴力法枚举法。
这里我用的是回溯法来进行暴力寻找最大期望分数,详解见代码注释
 

方法2:

更简单一些,直接计算出所有成绩的损失分数,复习最大的m个即可。

public class Demo2 {



    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();
        int m = sc.nextInt();

        int[] p =new int[n];

        int[] score =new int[n];

        for (int i = 0; i < n; i++) {

            p[i]=sc.nextInt();

        }
        for (int i = 0; i < n; i++) {

            score[i]=sc.nextInt();

        }

        boolean[] flag=new boolean[n];//用来标记哪些分数已经被复习了。这样之后求和就不用再算了
        Demo2.getmaxscore(flag,p,0,score,n,m,0);

        System.out.println(Demo2.max);

    }



    static int count=0;
    static double max=0;

    public static void getmaxscore(boolean[] flag,int[] p,double sum,int[] score,int n,int m,int start){//暴力出那m个数,再求一次和,更新当前最大值

        if(count==m){//当找出m个数时,停止回溯,开始计算剩下的那些没复习的和,将他们相加
            for (int i = 0; i < n; i++) {

                if(!flag[i]){//没有复习
                    sum+=score[i]*p[i]*0.01;
                }

            }
            max=Math.max(max, sum);//最后得出本次期望分数,和之前的比较,得到当前最大期望分数。然后本次递归查询结束,return后进行第二次的递归。。。重复进行 直到完毕。

            return;

        }

        for (int i = start; i < n; i++) {//回溯法的经典for循环,枚举出m个数,start是每次的起始位置
            sum+=score[i];//计算这m个数的和,乘100%,所以直接相加
            flag[i]=true;//标记为已复习
            count++;//count初始为0,每回溯一次就+1;
            getmaxscore(flag,p,sum,score,n, m, start+1);//
            sum=sum-score[i];//回溯法之撤回
            flag[i]=false;//同上
            count--;//同上
        }

    }

}












#美团笔试#
全部评论
楼主厉害啊,还好我没碰到这道题
点赞 回复 分享
发布于 2022-08-22 08:25 陕西

相关推荐

一颗宏心:华为HR晚上过了十二点后还给我法消息。
点赞 评论 收藏
分享
1 5 评论
分享
牛客网
牛客企业服务