老师计划比赛,每位参赛者必须完成20圈游泳,然后骑行10公里,然后跑3公里。例如,换句话说,第一个参赛者在20圈游泳,下车,并开始骑自行车。第一个人离开游泳池后,第二个参赛者开始游泳20圈;一旦他或她开始骑自行车,第三名选手开始游泳。 。 。等等
每位参赛者的预计游泳时间是指完成20圈游泳的预计时间,每位参赛者都有预计的骑行和跑步时间。问题是设计种族的时间表,以及对参赛者的开始进行排序的顺序。参与者可以同时骑自行车和比赛,但最多只有人可以在游泳池中。
问题:设计一个有效的算法来安排上述任务? 另外一个证明算法正确的程序。
尝试解决方案: 我想出了这个想法: 将参赛者从1到n初始化, 让si,bi,ri表示游泳,骑自行车和跑步时间的选手i。 我们按照循环时间的递减顺序排列参赛者+运行时间并按此顺序发送。 我不能正确地制定算法和程序,所以需要帮助。
答案 0 :(得分:3)
您只需要担心两个简单的规则:
考虑每位参赛者参加特定活动的时间:
Contestant->Swim time(mins)->Run time(mins)->Cycle time(mins)
A->1->1->1
B->2->1->1
C->1->1->1
案例1: 游泳时间最长的参赛者先行。比赛从B,A,C顺序的中午12:00开始,我们有:
Swimming complete->Running complete->Cycling complete
B->12:02->12:03->12:04
A->12:03->12:04->12:05
C->12:04->12:05->12:06
案例2: 游泳时间最长的参赛者排名第二。比赛从A,B,C的顺序在中午12:00开始,我们有:
Swimming complete->Running complete->Cycling complete
A->12:01->12:02->12:03
B->12:03->12:04->12:05
C->12:04->12:05->12:06
案例3: 游泳时间最长的参赛者排名第三。比赛从中午12点开始,按照A,C,B的顺序开始:
Swimming complete->Running complete->Cycling complete
A->12:01->12:02->12:03
C->12:02->12:03->12:04
B->12:04->12:05->12:06
你可以看到,在所有情况下,最后一名选手在12:06完成比赛。然而,在案例1(游泳时间最长的参赛者)中,第一个参赛者在下午12:04结束,第二个参赛者在12:05结束。如果是第二名(参赛者最大游泳时间排在第二位),第一名选手将在12:03完成比赛,第二名选手将在12:05完成比赛。在案例3(最大游泳时间的参赛者排名第三)中,第一个参赛者在12:03结束比赛,第二个参赛者在12:04结束比赛。这是迄今为止最有效的订单,因为到12点04分,你已经有两位参赛者完成了比赛。
但是,如果两个参赛者有相同的游泳时间但不同的周期和运行时间会怎样。考虑一下:
Contestant->Swim time(mins)->Run time(mins)->Cycle time(mins)
A->1->1->1
B->2->2->1
C->2->1->1
案例4 :在游泳时间相同的两名参赛者中,参赛者的骑行和跑步时间总和较低:
Swimming complete->Running complete->Cycling complete
A->12:01->12:02->12:03
C->12:03->12:04->12:05
B->12:05->12:07->12:08
案例5:在游泳时间相同的两位参赛者中,参赛者的骑行和跑步时间总和最高:
Swimming complete->Running complete->Cycling complete
A->12:01->12:02->12:03
B->12:03->12:05->12:06
C->12:05->12:06->12:07
可以看出,最后一名选手在第4组时间下午12:08完成比赛,而最后一名选手在第5组中以12:07结束比赛。这意味着如果两名选手拥有相同的游泳时间,骑自行车+跑步时间较长的选手应先行。
用Java编写代码:
首先创建一个类来保存参赛者信息:
public class Contestant {
private String name;
private Map<String,Integer> timings = new HashMap<>();
public Contestant(String name, Map<String, Integer> timings) {
this.name = name;
this.timings = timings;
}
public Integer getTimingFor(String activity) {
return timings.get(activity);
}
public Map<String, Integer> getTimings() {
return timings;
}
public String getName() {
return name;
}
}
然后创建一个比较器,决定哪个参赛者应该在另一个参赛者之前。这个想法是按照游泳时间(升序)的顺序命令参赛者,然后按剩余活动的顺序(降序)命令
public class ContestantComparator implements Comparator<Contestant> {
@Override
public int compare(Contestant one, Contestant two) {
int contestantOneSwimTime = one.getTimingFor("Swimming");
int contestantTwoSwimTime = two.getTimingFor("Swimming");
if(contestantOneSwimTime<contestantTwoSwimTime) {
return -1;
} else if(contestantOneSwimTime>contestantTwoSwimTime) {
return 1;
} else {
int c1RemainingTimeExceptSwimming = 0;
int c2RemainingTimeExceptSwimming = 0;
for(String activity : one.getTimings().keySet()) {
if(!activity.equals("Swimming")) {
c1RemainingTimeExceptSwimming+=one.getTimingFor(activity);
}
}
for(String activity : two.getTimings().keySet()) {
if(!activity.equals("Swimming")) {
c2RemainingTimeExceptSwimming+=two.getTimingFor(activity);
}
}
if(c1RemainingTimeExceptSwimming>c2RemainingTimeExceptSwimming) {
return -1;
} else if(c1RemainingTimeExceptSwimming<c2RemainingTimeExceptSwimming) {
return 1;
} else {
return 0;
}
}
}
}
使用代码的主类:
public class Contest {
public static void main(String []args) {
Map<String,Integer> timings = new HashMap<String,Integer>();
timings.put("Swimming", 1);
timings.put("Running", 1);
timings.put("Cycling", 1);
Contestant a = new Contestant("A",timings);
timings = new HashMap<String,Integer>();
timings.put("Swimming", 1);
timings.put("Running", 2);
timings.put("Cycling", 1);
Contestant b = new Contestant("B",timings);
timings = new HashMap<String,Integer>();
timings.put("Swimming", 1);
timings.put("Running", 2);
timings.put("Cycling", 2);
Contestant c = new Contestant("C",timings);
List<Contestant> contestants = new ArrayList<Contestant>();
contestants.add(a);
contestants.add(b);
contestants.add(c);
Collections.sort(contestants,new ContestantComparator());
for(Contestant contestant : contestants) {
System.out.println(contestant.getName());
}
}
}
请注意,参赛者课程包含地图。此映射的目的是允许您为参赛者添加任意数量的任务,而无需更改代码。键表示游泳等活动,值(整数)表示相应活动的时间。
答案 1 :(得分:-1)
这是一个贪婪编程的明显案例(注意:贪婪总是不是最佳选择): 我在这里假设您希望最小化总时间,因为这里没有提到。
算法:
让si,bi,ri表示游泳,骑自行车和跑步时间的选手i。
在完成所有三项任务时,对参赛者进行排序,按降序对其进行排序。
根据步骤2中的顺序安排它们
对参赛者进行排序:
计算每个人游泳,骑车和跑步所需的时间。
添加这些时间,并按降序排序。