网易在线编程题 奖学金问题
小v今年有n门课,每门都有考试,为了拿到奖学金,小v必须让自己的平均成绩至少为avg。每门课由平时成绩和考试成绩组成,满分为r。现在他知道每门课的平时成绩为ai ,若想让这门课的考试成绩多拿一分的话,小v要花bi 的时间复习,不复习的话当然就是0分。同时我们显然可以发现复习得再多也不会拿到超过满分的分数。为了拿到奖学金,小v至少要花多少时间复习。
输入描述:
第一行三个整数n,r,avg(n大于等于1小于等于1e5,r大于等于1小于等于1e9,avg大于等于1小于等于1e6),接下来n行,每行两个整数ai和bi,均小于等于1e6大于等于1
输出描述:
一行输出答案。
输入例子:
5 10 9
0 5
9 1
8 1
0 1
9 100
输出例子:
43
我是按照多重背包问题来求解的,因为没有任何优化,所以运行超时。先记录下来,如果以后有时间再进行优化。
1 import java.util.Arrays; 2 import java.util.Scanner; 3 4 public class ReviewedTime{ 5 6 public static void main(String[] args)throws Exception{ 7 Scanner scanner=new Scanner(System.in); 8 9 while(scanner.hasNext()){ 10 int n = scanner.nextInt(); 11 int r = scanner.nextInt(); // 每门课的满分 12 int avg = scanner.nextInt(); 13 int[] a=new int[n]; // 每门课的平时成绩 14 int[] b=new int[n]; // 每门得一分所需要的复习时间 15 int[] c=new int[n]; // 每门课最多可以提高的分数 16 int totalScoresNeeded=0; //为了达到目标需要提高的总分数 17 18 for(int i=0;i<n;i++){ 19 a[i]=scanner.nextInt(); 20 b[i]=scanner.nextInt(); 21 c[i]=r-a[i]; 22 23 totalScoresNeeded+=avg-a[i]; 24 } 25 26 int time=new ReviewedTime().getLeastReviewedTime(c,b,totalScoresNeeded); 27 System.out.println(time); 28 } 29 30 31 } 32 33 /** 34 * dp[i][j] 表示前i门课得到分数j所需要的最少时间 35 * dp[i][j]=min{dp[i-1][j-k]+k*b[i] | 0<=k<=c[i]&&k<=j} 36 * @param c c[i]表示第i门课可以提高的分数 37 * @param b b[i]表示每提高第i门课一分需要花费的时间 38 * @param totalScoresNeeded 39 * @return 40 */ 41 public int getLeastReviewedTime(int[] c, int[] b,int totalScoresNeeded){ 42 if(c.length==0 || c==null || totalScoresNeeded<0) 43 return -1; 44 int[][] dp=new int[c.length][totalScoresNeeded+1]; 45 int max=Integer.MAX_VALUE; 46 int n=c.length; 47 48 for(int j=1;j<=totalScoresNeeded;j++){ 49 dp[0][j]=max; //表示花再多时间都没办法达标 50 if(j<=c[0]){ 51 dp[0][j]=j*b[0]; 52 } 53 } 54 55 for(int i=1;i<n;i++){ 56 for(int j=1;j<=totalScoresNeeded;j++){ 57 dp[i][j]=dp[i-1][j]; 58 for(int k=1; k<=c[i]&&k<=j; k++){ 59 if(dp[i-1][j-k]!=max) 60 dp[i][j]=Math.min(dp[i][j], dp[i-1][j-k]+k*b[i]); 61 } 62 } 63 } 64 65 return dp[n-1][totalScoresNeeded]!=max ? dp[n-1][totalScoresNeeded]:-1; 66 } 67 }