031402304 陈燊
031401433 张斯巍
一、问题重述
编码实现一个毕设导师的智能匹配的程序。提供输入包括:30个老师(包含带学生数的要求的上限,单个数值,在[0,8]内),100个学生(包含绩点信息),每个学生有5个导师志愿(志愿的导师可以重复但不能空缺)。实现一个智能自动分配算法,根据输入信息,输出导师和学生间的匹配信息(一个学生只能有一个确认导师,一个导师可以带少于等于其要求的学生数的学生)及未被分配到学生的导师和未被导师选中的学生。
二、问题分析
问题描述中要求测试数据自写程序随机生成,现实中存在着许多影响因素,但为保证分配算法不至于太过复杂, 因此生成测试数据时只考虑绩点因素。而在简化版的毕设导师分配系统中,对分配结果起到决定性作用的也就只有两个因素——志愿顺序和优先级。为使成绩靠前的学生尽量学到自己满意的导师,我们拟定采取导师学生名单满后按照绩点顺序进行筛选的方法进行导师的分配。
三、核心算法
在实际毕设导师选择的时候,若采用双向选择,则需考虑到众多因素。这里为了数据处理方便,在导师选择的时候只考虑绩点这一关键因素,即根据绩点排序进行学生的筛选。 整个算法大致步骤如下所示:
- 程序随机生成学生信息、导师信息等测试数据
- 算法进行五轮分配,在第i轮时,依次检索所有学生的第i个志愿填报情况
- 将该学生添加进第i个志愿所对应导师的学生名单
- 若该志愿所对应导师的学生名单未达其设定学生数上限,则进行下一个学生的检索
- 若该该志愿所对应导师的学生名单超过其设定学生数上限,则将其学生名单按照绩点进行排序
- 将绩点排名最后的学生移除该导师的学生名单,并设定该学生状态为未选中导师,在下一轮时再次对其进行分配
- 算法进行五轮分配完毕,输出分配结果,程序运行结束。
算法流程图:
四、代码分析
实现语言:JAVA
开发平台:Eclipse
- 学生类
public class Student {
//学号
private int studentID;
//绩点
private double score;
//姓名
private String name;
//导师工号
private int teaID;
//五个志愿
private int[] chooseTeacher = new int[5];
- 导师类
public class Teacher {
//优先队列因子,绩点小的在对头
Comparator<Student> OrderIsdn = new Comparator<Student>(){
public int compare(Student s1, Student s2) {
if(s1.getScore() >= s2.getScore()) {
return 1;
} else if (s1.getScore() < s2.getScore()) {
return -1;
} else {
return 0;
}
}
};
//保存导师的学生名单,优先队列结构可使学生根据绩点竞争筛选时更为简单
private Queue<Student> student = new PriorityQueue<Student>(10, OrderIsdn);
//姓名
private String name;
//导师工号
private int teaID;
//学生数上限
private int stu_num_max;
- 随机生成学生数据,考虑实际情况,学生绩点的生成范围为1.0~4.5
public void initStudentData() {
for (int i = 0; i < STU_NUMBERS; i ++) {
students[i] = new Student();
students[i].setStudentID(i + 1);
if (i < 9) {
students[i].setName("student_0" + (i + 1));
} else {
students[i].setName("student_" + (i + 1));
}
//根据现实情况,随机生成的绩点信息范围在1.0~4.5
students[i].setScore(((double)rand.nextInt(3500) + 1000) / 1000);
int tempID;
int[] tempTea = new int[5];
for (int k, j = 0; j < 5; j ++) {
tempID = rand.nextInt(TEA_NUMBERS) + 1;
for (k = 0; k < j; k ++) {
if (tempTea[k] == tempID) {
j --;
break;
}
}
if (k == j) {
tempTea[j] = tempID;
}
}
students[i].setChooseTeacher(tempTea);
}
}
- 随机生成导师数据,包括工号、姓名、学生数上限等信息
public void initTeacherData() {
for (int i = 0; i < TEA_NUMBERS;i ++) {
teachers[i] = new Teacher();
teachers[i].setTeaID(i + 1);
if (i < 10) {
teachers[i].setName("teacher_0" + (i + 1));
} else {
teachers[i].setName("teacher_" + (i + 1));
}
teachers[i].setStu_num_max(rand.nextInt(9));
}
}
- 导师分配系统核心算法
public void distTeacher() {
for (int i = 0; i < 5; i ++) {
for (int k = 0; k < STU_NUMBERS; k ++) {
if (students[k].getTeaID() == 0) {
int index = students[k].getChooseTeacher()[i] - 1;
students[k].setTeaID(index + 1);
teachers[index].getStudent().add(students[k]);
if (teachers[index].getStudent().size() > teachers[index].getStu_num_max()) {
students[teachers[index].getStudent().peek().getStudentID() - 1].setTeaID(0);
teachers[index].getStudent().poll();
}
}
}
}
}
- 算法运行完成后,输出分配结果至data.txt文档
public void printData() throws IOException {
int count = 0;
String temp;
File file=new File("data.txt");
if(file.exists()) {
file.delete();
} else {
file.createNewFile();
}
FileWriter fileWriter=new FileWriter(file);
@SuppressWarnings("resource")
BufferedWriter bufferedWriter=new BufferedWriter(fileWriter);
//输出学生信息,包括分配的导师
bufferedWriter.write("***********************
");
bufferedWriter.write("--------学生信息---------
");
bufferedWriter.write("***********************
");
for (int i = 0; i < STU_NUMBERS; i ++) {
bufferedWriter.write("学号:" + students[i].getStudentID() + "" + "
");
bufferedWriter.write("姓名:" + students[i].getName() + "
");
bufferedWriter.write("绩点:" + students[i].getScore() + "" + "
");
bufferedWriter.write("五个导师志愿:");
for (int j = 0; j < 5; j ++) {
bufferedWriter.write(students[i].getChooseTeacher()[j] + " ");
}
bufferedWriter.write("
");
if (students[i].getTeaID() == 0) {
temp = "无";
} else {
temp = students[i].getTeaID() + "";
}
bufferedWriter.write("已分配导师:" + temp + "
");
bufferedWriter.write("
");
}
//输出导师信息,包括导师的学生名单
bufferedWriter.write("***********************
");
bufferedWriter.write("--------导师信息---------
");
bufferedWriter.write("***********************
");
for (int i = 0; i < TEA_NUMBERS; i ++) {
bufferedWriter.write("导师工号:" + teachers[i].getTeaID() + "" + "
");
bufferedWriter.write("姓名:" + teachers[i].getName() + "
");
bufferedWriter.write("学生数上限:" + teachers[i].getStu_num_max() + "" + "
");
bufferedWriter.write("学生名单:" + "
");
for (Student stu : teachers[i].getStudent()) {
count ++;
bufferedWriter.write(" " + stu.toString() + "
");
}
bufferedWriter.write("
");
}
bufferedWriter.write("***********************
");
bufferedWriter.write("未分配人数:" + (STU_NUMBERS - count) + "
"
+ "导师分配成功率为:" + count + "%" + "
");
bufferedWriter.flush();
System.out.println("导师分配系统运行成功!
导师分配结果信息已保存至data.txt文档里!");
}
五、结果分析
运用程序进行了十次样本测试,测试结果如下:
次数 | 学生总数 | 导师总数 | 未分配学生数 | 未分配导师数 | 匹配率 |
---|---|---|---|---|---|
第一次 | 100 | 30 | 3 | 4 | 97% |
第二次 | 100 | 30 | 1 | 1 | 99% |
第三次 | 100 | 30 | 9 | 3 | 91% |
第四次 | 100 | 30 | 0 | 1 | 100% |
第五次 | 100 | 30 | 3 | 6 | 97% |
第六次 | 100 | 30 | 2 | 2 | 98% |
第七次 | 100 | 30 | 6 | 4 | 94% |
第八次 | 100 | 30 | 2 | 2 | 98% |
第九次 | 100 | 30 | 7 | 4 | 93% |
第十次 | 100 | 30 | 4 | 4 | 96% |
平均 | 100 | 30 | 2.9 | 3.1 | 96.3% |
分析:
从结果表中可以看出,平均未分配学生数为2.9,未分配到学生的导师数为3.1,且导师分配成功的学生比例高达96.3%!这充分表明了我们的的算法基本满足了题意要求。
示例:
分配结果示例链接
六、程序评价
本毕设导师智能分配程序的分配结果基本满足了题意要求,但是程序尚且存在着一些不足。在随机生成的学生信息和导师信息数据和现实生活中有所偏颇。一方面在导师志愿填写的时候,往往存在一些热门老师和冷门导师,这些导师受学生的关注度有着较大的差别,然而在程序随机生成数据的时候,并未考虑进这个因素,而是把所有导师在志愿填报上面的概率设为一致;另一方面,在实际中,学生的绩点信息往往会呈现出一种两端少,中间多的情况,而在生成数据的时候却还是把绩点生成的范围设为一致。这两个方面在一定程度上面对分配结果会产生一定的影响。
七、总结
031401433 张斯巍
两个人一起想算法,写代码真的比一个人单干有趣的多,特别是两个人的不同的想法提出来之后,通过分析优缺点以及讨论最终实现的方案,会比一个人的想法更加的全面,更加具有可行性。当一个想法不能持续下去时,队友之间能够互相打气,查找相关资料后,最终完成了我们的代码。这次结对作业针对实际问题要求用程序来实现,不仅需要导师匹配,还需要考虑一些其他的因素,我们讨论了一下想要用java实现,由于我的队友编程能力比较强,一些想法还有编程都是队友提供帮助的。
031402304 陈燊
本次作业的工作量相对上一次而言少了挺多,因为在上一次作业的需求分析中,我们对这个毕设智能分配系统已经做了一个充分的讨论,而本次算法的实现思路和我们之前的想法大致也是一样的,又加上我本身JAVA基础掌握得较为牢固,因此在几个小时之内便完成的程序的整体实现。整个程序设计过程中的难点,我觉得应该便是如何让随机生成的数据更贴合实际,在现实生活中,绩点信息和志愿填报情况往往都存在着一定的规律,比如绩点分布在2.0~3.2等中上水平的同学占绝大多数部分,而志愿填报时也经常存在热门导师,导师在选择学生的时候,也并非仅仅只参照绩点情况,还有专业兴趣技能特长等等,如何把这些因素综合考虑进去,生成一个基本贴合实际情况的数据,也是程序的一个要点。在整个过程当中,我仔细阅读其他组的数据随机生成方法,发现都没有考虑这些。因此我觉得即使算法实现得非常巧妙,但在缺乏真实合理的测试数据之下,所运行出来的结果并不具备多大的参考价值。
项目链接