2020-11-23
奖学金问题(动态规划)
题目描述
小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
输出描述:
一行输出答案。
示例1:
输入
5 10 9<br />0 5<br />9 1<br />8 1<br />0 1<br />9 100<br />
输出
43
方法一:
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
int n = sc.nextInt();
int r = sc.nextInt();
int avg = sc.nextInt();
long time = 0;
long total = 0;
ArrayList<FuXi> list = new ArrayList();
for(int i=0; i<n; i++){
long ai = sc.nextLong();
total += ai;
list.add(new FuXi(ai, sc.nextLong()));
}
total = n * avg - total;
if(total <= 0){
System.out.println(0);
continue;
}
Comparator<FuXi> c = new Comparator<FuXi>(){
public int compare(FuXi f1, FuXi f2){
if(f1.bi <= f2.bi){
return -1;
}else{
return 1;
}
}
};
Collections.sort(list, c);
for(int i=0; i<list.size(); i++){
FuXi f = list.get(i);
if(total <= r - f.ai){
time += total * f.bi;
break;
}else{
time += (r - f.ai) * f.bi;
total -= r - f.ai;
}
}
System.out.println(time);
}
}
}
class FuXi{
long ai;
long bi;
public FuXi(long ai, long bi){
this.ai = ai;
this.bi = bi;
}
}
方法二:
import java.util.Scanner;
import java.util.Arrays;
class Score implements Comparable<Score>{
private int score;
private int time;
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public int getTime() {
return time;
}
public void setTime(int time) {
this.time = time;
}
@Override
public int compareTo(Score o) {
if(this.time>o.time) return 1;
else if(this.time==o.time) return 0;
else return -1;
}
public Score(int score, int time) {
super();
this.score = score;
this.time = time;
}
}
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
while(sc.hasNextInt()){
int n=sc.nextInt();
int r=sc.nextInt();
int avg=sc.nextInt();
int init=n*avg;//总的平均值
long result=0;//所需时间,最后的结果可能超过了int数据,所以改为long
Score[] score=new Score[n];
for (int i = 0; i < n; i++) {
score[i]=new Score(sc.nextInt(), sc.nextInt());
init-=score[i].getScore();
}//数据初始化完毕
Arrays.sort(score);//排序完毕
for (int i = 0; i < n; i++) {
if(init>0){
if(r-score[i].getScore()<init){
result+=(r-score[i].getScore())*score[i].getTime();
init-=(r-score[i].getScore());
}else{
result+=init*score[i].getTime();
init=0;//结束
}
}else{
break;
}
}
//先去学价值最好的课程,学满为止
System.out.println(result);
}
}
}
方法三:(结构挺清晰)
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNext()) { //注意while处理多个case
int n = in.nextInt();
long r = in.nextLong();
long avg = in.nextLong();
long[][] arr = new long[n][2];
long total = avg*n; //需要的分数
long score = 0; //现在的分数
for(int i = 0;i<n;i++){
arr[i][0] = in.nextLong(); //平时成绩
arr[i][1] = in.nextLong(); //时间
score += arr[i][0];
}
sort(arr);
long time = 0;
int i = 0;
while(score<total&&i<n){
if(arr[i][0]<r){
//第i门课没有满分
time += arr[i][1];
score++;
arr[i][0] += 1;
}else{
i++;
}
}
System.out.println(time);
}
in.close();
}
//对时间进行排序
public static void sort(long[][]a){
for(int i = 0;i<a.length-1;i++){
boolean flag = true;
for(int j = 0;j<a.length-1-i;j++){
if(a[j][1]>a[j+1][1]){
long temp = a[j][0];
long temp2 = a[j][1];
a[j][0] = a[j+1][0];
a[j+1][0] = temp;
a[j][1] = a[j+1][1];
a[j+1][1] = temp2;
flag = false;
}
}
if(flag)
return;
}
}
}