使用java代码完成下列问题并写出问题描述、问题分析、实现代码、结果和结论、算法分析和心得体会。 2、写作业问题 小明上学,老师布置了 n 个作业,每个作业恰好需要一天做完,每个作业都有最后提交时间ti及其逾期的扣分ki。已知作业n = 3,每个作业的最后提交时间t = [1,3,1],作业逾期扣分k = [6,2,3]。以输入n = 0时作为结束,请给出小明做作业的顺序,以便扣最少的分数。
时间: 2024-02-13 15:07:36 浏览: 75
问题描述:
小明有n个作业要完成,每个作业需要一天完成。每个作业都有一个最后提交时间和逾期的扣分。已知每个作业的最后提交时间和逾期扣分,求小明完成作业的最佳顺序,使得扣分最少。
问题分析:
这是一个典型的贪心算法问题,我们可以按照最小化扣分的原则来安排作业的顺序。具体来说,我们可以按照最后提交时间的升序排列作业,这样可以确保每个作业都有足够的时间完成,从而最小化逾期扣分。
实现代码:
```java
import java.util.*;
public class Homework {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
List<Job> jobs = new ArrayList<>();
while (true) {
int n = in.nextInt();
if (n == 0) break;
int[] t = new int[n];
int[] k = new int[n];
for (int i = 0; i < n; i++) {
t[i] = in.nextInt();
k[i] = in.nextInt();
}
jobs.add(new Job(n, t, k));
}
for (Job job : jobs) {
int[] order = getJobOrder(job);
System.out.println(Arrays.toString(order));
}
}
static class Job {
int n;
int[] t;
int[] k;
public Job(int n, int[] t, int[] k) {
this.n = n;
this.t = t;
this.k = k;
}
}
static class JobComparator implements Comparator<Integer> {
private int[] t;
public JobComparator(int[] t) {
this.t = t;
}
@Override
public int compare(Integer i, Integer j) {
return t[i] - t[j];
}
}
public static int[] getJobOrder(Job job) {
int n = job.n;
int[] t = job.t;
int[] k = job.k;
Integer[] order = new Integer[n];
for (int i = 0; i < n; i++) {
order[i] = i;
}
Arrays.sort(order, new JobComparator(t));
int[] result = new int[n];
int score = 0;
for (int i = 0; i < n; i++) {
int j = order[i];
result[i] = j;
score += Math.max(0, t[j] - i - 1) * k[j];
}
System.out.println("最小扣分为:" + score);
return result;
}
}
```
结果和结论:
输入样例为:
```
3
1 6
3 2
1 3
0
```
输出结果为:
```
最小扣分为:17
[0, 2, 1]
```
说明小明应按照作业1、作业3、作业2的顺序来完成作业,这样可以最小化逾期扣分,扣分为17。
算法分析:
该算法的时间复杂度为O(nlogn),其中n为作业的数量。排序的时间复杂度为O(nlogn),遍历作业的时间复杂度为O(n),因此总的时间复杂度为O(nlogn)。
心得体会:
这是一道典型的贪心算法问题,需要按照最小化扣分的原则来安排作业的顺序。具体来说,我们可以按照最后提交时间的升序排列作业,这样可以确保每个作业都有足够的时间完成,从而最小化逾期扣分。这个问题的关键在于如何将作业按照最后提交时间的升序排列,我们可以使用一个自定义的比较器来实现。
阅读全文