第二次结对编程作业——毕设导师智能匹配
031402337 胡心颖
031402341 王婷婷
作业概述
编码实现一个毕设导师的智能匹配的程序。
提供输入包括:30个老师(包含带学生数的要求的上限,单个数值,在[0,8]内),100个学生(包含绩点信息),每个学生有5个导师志愿(志愿的导师可以重复但不能空缺)。
实现一个智能自动分配算法,根据输入信息,输出导师和学生间的匹配信息(一个学生只能有一个确认导师,一个导师可以带少于等于其要求的学生数的学生) 及 未被分配到学生的导师 和 未被导师选中的学生。
作业要求
- 输入的数据,另外写生成程序随机实现。
- 为输入输出设计标准化、通用化、可扩展的接口,为该智能匹配程序模块后期可能的整合入系统提供便利。
- 输入输出的格式,如采用文本文件或数据库的方式输入,可自由讨论确定,但需要明确,为后期可能的整合入系统提供便利。
- 需要为智能匹配算法确立几条分配或排序原则,比如 绩点优先、或其他、或其他等等,请你们结对讨论确定。
- 算法评价的目标是:对于同一组输入,输出的未被导师选中的学生数越少越好。
- 代码具有规范性。
- 实现的程序语言不做限制性要求。
- 代码提交在https://coding.net 上。
- 两个人共同撰写一个博客,包含上述内容的描述,同时包含结对感受,以及两个人对彼此结对中的闪光点或建议的分享。
作业分析
算法思想为采用 贪心思想 ;
简单来说,首先将学生按照绩点从高到低排序,优先分配绩点高的学生;
然后针对每个学生,首先过滤掉其重复选择的导师,然后按照权重值 teacher[i].qz (后面介绍)高低来分配导师,权重值相同的情况下按照学生志愿排序;
teacher[i]表编号为i的导师,teacher[i].left表示该导师剩余学生数,teacher[i].want表示选择了该导师的学生总数,teacher[i].qz表示teacher[i]导师对于该学生的权重值(在本算法中可认为是匹配程度,越大越匹配)
对于每个学生的五个志愿导师,都计算出其对应的权重值,按照权重值高的分配,如果有多个权重值相同,那么则按照志愿顺序分配;
从权重值计算公式可以看出,teacher[i].left越大,teacher[i].want越少,代表导师剩余数越多和导师越冷门来分配,在符合学生志愿的情况下,使得大多数学生都能分配到导师;
权重值相同时按照志愿顺序来分配,使得学生都能选择到自己较喜爱的导师
流程图
代码分析
基本数据结构
struct Student // 学生结构体
{
int num;//学生编号
double grade;//学生绩点
bool flag;//是否分配了导师
int tea[10];//志愿
}stu[110];
struct Teacher //老师结构体
{
int num;//导师编号
double need;//可以接受的学生数
double left;//还剩下的名额
double want;//被几个学生选择
double qz;//权重,qz=left/need
bool flag;//是否有学生
vector<int> stu;//接受的学生
}teacher[50];···
产生随机数据
srand(time(0));
for(int i=0;i<30;i++)//导师随机数据
{
int want;
want=rand()%9;
fprintf(f,"%d %d
",i,want);
}
for(int i=0;i<100;i++)//学生随机数据
{
int g=rand()%500;
if(g<=100)g+=100;
double grade=(double)g/100.0;
fprintf(f,"%d %lf %d %d %d %d %d
",i,grade,rand()%30,rand()%30,rand()%30,rand()%30,rand()%30);
}
使用srand()函数创造随机数;
导师随机生成想要的学生个数,将随机数模9,使得数据范围在 0-8 之间;
学生随机生成绩点以及想要的导师编号,绩点控制在1-5之间,导师编号在0-29之间
权重值teacher[i].qz
for(int i=0;i<30;i++)//计算导师权重
{
teacher[i].left=teacher[i].need;
if(teacher[i].want==0)teacher[i].qz=-1;
else teacher[i].qz=teacher[i].left/teacher[i].want;
}
teacher[i]表编号为i的导师,teacher[i].left表示该导师剩余学生数,teacher[i].want表示选择了该导师的学生总数;
如果导师想要的学生数为0 ,则直接将teacher[i].qz(权重值)设为-1,
否则权重值teacher[i].qz=teacher[i].left/teacher[i].want
绩点排序函数
bool cmp(Student a,Student b)//学生按照绩点的高到低排序
{
return a.grade>b.grade;
}
将学生按照绩点的高到低排序
导师分配函数
sort(stu,stu+100,cmp);//学生排序
for(int i=0;i<100;i++)
{
double now;
int ans;
now=0;
ans=-1;
for(int j=0;j<5;j++)
{
if(now<teacher[stu[i].tea[j]].qz)/到志愿导师中权重最高的导师
{
now=teacher[stu[i].tea[j]].qz;
ans=stu[i].tea[j];
}
}
if(ans==-1)continue;//如果找不到符合要求的导师就下一个
teacher[ans].stu.push_back(i);//修改导师的剩余名额以及其他信息
teacher[ans].left--;
teacher[ans].want--;
teacher[ans].qz=teacher[ans].left/teacher[ans].want;
if(teacher[ans].flag==0)
{
countt--;
teacher[ans].flag=1;
}
stu[i].flag=1;//修改学生的信息
counts--;
}
先将学生按照绩点初步排序,在通过权重值和志愿顺序来分配
程序运行结果
生成随机数据样例
使用srand()函数创造随机数;
导师编号从0至29,后面紧跟导师想要的学生数从0到8
学生编号从0至99,后面紧跟其绩点 从1.00到5.00,再接着就是五个志愿导师
https://coding.net/u/songyufeng/p/DSFPXT/git/blob/master/data.txt
匹配结果样例
经过匹配之后的结果:
首先输出没有匹配的导师以及没有匹配的学生,
紧接着按照导师序号来输出每个导师的匹配学生情况
https://coding.net/u/songyufeng/p/DSFPXT/git/blob/master/ans.txt
算法效率评估、闪光点、改进方向
效率评估
- 以下是10次随机试验的学生分配情况结果
- 从图表中数据来看几乎所有学生都能够分配到导师,近乎完美,不得不感叹过贪心算法真的超级棒啊!
- 那么学生的志愿情况呢,是每个学生都能分配到其志愿靠前的导师?
- 以下是10次随机试验的学生志愿平均情况(只计算了有被分配到的学生)
- 从图表中可以看出 第一志愿人数>第二志愿>第四志愿>第三志愿>第五志愿
- 根据我们先前的优先分配绩点高的同学的思想,想必绩点高的同学所分配的志愿自然是比较靠前的,下面我们也验证一下这一点
- 按照绩点段来查看志愿情况
- 由于绩点是随机生成的,所以各个绩点段的人数相同(这也是我们考虑不周到、比较不科学的地方,因为现实生活中绩点不可能平均分配)
- 绩点为 [4.00 - 5.00 )的绩点大神
- 绩点为 [3.00 - 4.00 )的学霸
- 绩点为 [2.00 - 3.00 )的伪学霸
- 绩点为 [1.00 - 2.00 )的学渣吧
- 图标完美验证了按照绩点优先分配的情况
闪光点
- 算法的思想 - 贪心思想
- 对于某个学生重复选择某位导师的情况,系统能够过滤掉
- 能够保证 最广大学生 分配到自己志愿的导师的情况,又可满足 绩点高者优先分配 以及尽可能 分配志愿靠前的导师 !
改进方向
- 学生绩点生成得不够合理,不够满足现实情况,影响了后面的志愿情况分析
作业感想
- 宋御风:结对编程比一个人编程感觉更加集中,在第二次结对编程作业,构思分配算法的时候,一个人很容易导致思维僵化,两个人探讨,听取对方的意见,效率会快很多。一个人编程经常完成一个模块的内容就想休息,两个人在一起会强迫自己做下去。而且如果两个人的思维和知识面互补的话,对项目各方面的完善都很有助益。
- wangtingting007:结对编程有助于克服拖延症,摆脱懒癌患者的毛病,同时结对过程能够与队友好好沟通、交流想法等,真的是一件很棒的事!然后结对过程能够结合两个人的特长和不足合理分工、提高作业效率和质量!队友代码能力好强!!!!
作业链接:https://coding.net/u/songyufeng/p/DSFPXT/git
项目说明:README.md
分配导师:a.cpp