再次做作业
求解方法 贪心算法
知识点 贪心算法、自定义排序、自定义类(特殊)输入
解题思路(完整AC代码再在最下方):
1.贪心点分析:
对于所有的作业,按照分数从高到低排序,分数相同时,截止时间小的排在前面。另外初始化一个大小为 [1005] 的数组,用来保存某一天是否已经被占用 (排序可以采用Comparator或Comparable实现,许多题解采用Comparator实现,本文介绍采用Comparable实现的方法)。
- 然后开始贪心,对于每份作业,看从当天到当前之前的时间里面,有没有空余,
- 如果有空余,安排到空余且天数最大的一天;
- 如果没有空余,这份作业只能被扣分。
2.自定义Comparable排序:
直接将自定义类实现Comparable接口,并实现其中的compareTo方法,按照自己定义的排列顺序将不同属性定义为不同级别的升降序排列,在排序时直接使用Collections或Arrays的sort方法将集合或数组传入即可(示例):
class Node implements Comparable<Node>{
public int d;
public int c;
public Node(int d) {
this.d=d;
}
@Override
public int compareTo(Node node) {
// TODO 自动生成的方法存根
//分数降序,天数升序排列
if(this.c!=node.c) {
return node.c-this.c; //降序:别人的减去自家的
}
else {
return this.d-node.d; //升序:自家的减去别人的
}
}
}
3.特殊自定义结点输入:
当题目要求一次性输入自定义节点的某一个属性时(本题),可以采用如下的方法(在结点中定义某一个属性的构造方法方法,另一个属性再通过赋值的方法给予值):
List<Node> list=new ArrayList<Node>();
for(int i=0;i<n;i++) {
list.add(new Node(sc.nextInt()));
}
for(int i=0;i<n;i++) {
list.get(i).c=sc.nextInt();
}
Collections.sort(list); // 直接排序
问题描述:
Ignatius刚从第30届ACM / ICPC重返校园。现在,他有很多作业要做。每个老师都给他交作业的最后期限。如果Ignatius在截止日期之后交作业,则老师会降低其最终考试的分数。现在,我们假设每个人都要花一天的功课。因此,伊格纳修斯(Ignatius)希望您帮助他安排功课的顺序,以最大程度地降低分数。
输入:
输入包含几个测试用例。输入的第一行是单个整数T,它是测试用例的数量。随后是T测试用例。
每个测试用例都以一个正整数N(1 <= N <= 1000)开头,该正整数表示作业的数量。然后跟随两行。第一行包含N个整数,它们指示受试者的截止日期,而第二行包含N个整数,指示分数的降低。
输出:
对于每个测试用例,您应该输出最小的总降低分数,每个测试用例一行。
样例输入:
3
3
3 3 3
10 5 1
3
1 3 1
6 2 3
7
1 4 6 4 2 4 3
3 2 1 7 6 5 4
样例输出:
0
3
5
AC代码(java):
package 再次做作业;
import java.util.*;
//hdu-1789
class Node implements Comparable<Node>{ //自定义类型
public int d;
public int c;
public Node(int d) {
this.d=d;
}
@Override
public int compareTo(Node node) {
// TODO 自动生成的方法存根
if(this.c!=node.c) {
return node.c-this.c; //降序:别人的减去自家的
}
else {
return this.d-node.d;
}
}
}
public class Main {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int t=sc.nextInt();
int ans=0; //记录所扣分数
while(t-->0) {
int n=sc.nextInt();
List<Node> list=new ArrayList<Node>();
for(int i=0;i<n;i++) {
list.add(new Node(sc.nextInt()));
}
for(int i=0;i<n;i++) {
list.get(i).c=sc.nextInt();
}
Collections.sort(list);
int i,j;
int[] flag=new int[1005]; //标记此天数是否被占用过,因为最大值为1000,所以范围设置为1005
for(i=0;i<n;i++) {
for(j=list.get(i).d;j>=1;j--) { //j的范围设置大于1,是因为天数是大于等于1的
if(flag[j]==0) {
flag[j]=1;
break;
}
}
if(j<1) {
ans+=list.get(i).c;
}
}
System.out.println(ans);
ans=0;
}
}
}