毕设导师智能匹配
毕设导师智能匹配
031402615 林昊斌
0314026 朱松
项目地址:https://coding.net/u/zs_510/p/test/git
问题描述
编码实现一个毕设导师的智能匹配的程序。提供输入包括:30个老师(包含带学生数的要求的上限,单个数值,在[0,8]内),100个学生(包含绩点信息),每个学生有5个导师志愿(志愿的导师可以重复但不能空缺)。实现一个智能自动分配算法,根据输入信息,输出导师和学生间的匹配信息(一个学生只能有一个确认导师,一个导师可以带少于等于其要求的学生数的学生) 及 未被分配到学生的导师 和 未被导师选中的学生。
问题要求
- 输入的数据,另外写生成程序随机实现。
- 为输入输出设计标准化、通用化、可扩展的接口,为该智能匹配程序模块后期可能的整合入系统提供便利。
- 输入输出的格式,如采用文本文件或数据库的方式输入,可自由讨论确定,但需要明确,为后期可能的整合入系统提供便利。
- 需要为智能匹配算法确立几条分配或排序原则,比如 绩点优先、或其他、或其他等等,请你们结对讨论确定。
- 算法评价的目标是:对于同一组输入,输出的未被导师选中的学生数越少越好。
- 代码具有规范性。
- 实现的程序语言不做限制性要求。
- 代码提交在https://coding.net 上。提交和使用方法,本周六助教会通过git和github使用讲解。网站上也有对应视频,可先自行学习使用。
- 两个人共同撰写一个博客,包含上述内容的描述,同时包含结对感受,以及两个人对彼此结对中的闪光点或建议的分享。
问题分析
- 程序实现语言:C++
- 输入输出方式:采用文本文件输入输出
- 算法目标:输出未被导师选中的学生数越少越好
- 采用算法:基于匈牙利算法的KM算法
- 分配排序原则:根据学生的绩点point和志愿级数lv进行权重的计算
w=2*point+(6-lv)
,这样的权重能大概平衡绩点高志愿级数低和绩点低志愿级数高两种情况的优先级,既能体现出绩点优先,又能结合志愿优先,平衡两者之间的关系,令学生和老师的满意度都能提升
代码分析
随机数生成并输入到txt文件
srand((unsigned)time(NULL));
float point;
int i,j;
int tn[101]; //教师要带的学生
int sx=100; //学生数
int tx=30; //教师数
ofstream input;
input.open("input.txt");
input<<sx<<" "<<tx<<endl; //学生数和教师数的文件输入
//这是教师带的学生随机数生成!
for(i=0;i<tx;i++)
{
tn[i]=(rand() % 9);
input<<tn[i]<<" ";
}
input<<endl;
//这是学生和学生的志愿信息随机数生成!
for(i=0;i<sx;i++)
{
point= 0.1*(float)(rand() % 50);
input<<i<<" "<<point<<endl; //学生信息文件输入
for(j=0;j<5;j++) //学生的志愿信息文件输入
{
input<<(rand() % tx)<<" "<<j+1<<" ";
}
input<<endl;
}
核心算法
bool find(int x) //增广轨搜索
{
if(st[x]!=-1)
return true;
visx[x] = true;
for(int y = 0; y < ny; y++)
{
if(visy[y] >= tn[y]) //教师选择的学生数量超过设定后跳过
continue;
float t = lx[x] + ly[y] - w[x][y];
if(t==0)
{
visy[y] += 1;
if(linky[y]==-1 || find(linky[y]))
{
linky[y] = x;
st[x]=y; //记录学生和分配到的导师
return true;
}
}
else if(slack[y] > t)
slack[y] = t;
}
return false;
}
int KM()
{
int i,j;
memset(linky,-1,sizeof(linky));
memset(ly,0,sizeof(ly));
for(i = 0; i < nx; i++)
for(j = 0,lx[i] = -INF; j < ny; j++)
if(w[i][j] > lx[i])
lx[i] = w[i][j];
for(int x = 0; x < nx; x++)
{
for(i = 0; i < ny; i++)
slack[i] = INF;
while(true)
{
if(find(x)) //找到增广轨,退出
break;
float d = INF; //未找到增广轨
for(i = 0; i < ny; i++)
{
if(!visy[i] && d > slack[i])
d = slack[i];
}
for(i = 0; i < nx; i++)
{
if(visx[i])
lx[i] -= d;
}
for(i = 0; i < ny; i++)
{
if(visy[i])
ly[i] += d;
else
slack[i] -= d;
}
}
}
float result = 0;
return result;
}
结果分析
因为算法限制,二部图中每个学生和导师间都存在权值(某个非0数值或0),所以每个学生和老师匹配后都能有一个结果,不过有一部分学生和导师的选择结果并不符合他们的意愿,这部分是由算法随机分配的,这时候可以进行第二轮的匹配筛选。
结对感受
林昊斌:
算法方面考虑的比较久,最后还是选择了KM算法,两个人都不是很擅长算法,所以在结对讨论时花费了大量的精力。随着结对时间的增加,越发感受到两个人的作业模式有多么的互补,原先一个人要弄很久的问题很快的就能解决,并且自身也在结对的过程总不停的完善。
朱松:
- 两个人各自都有自己的理解,但是都不完善,只要用合理的方式,通过两个人的讨论,沟通,一步步的扩充,明细,碰撞出更加璀璨的焰火。
- 两个人的学习能力会比单人简单,可以分别学习不同的方面,然后进行相互讲解,有个人引导会比自己摸索容易。
闪光点和建议的分享
- 结对过程中有自己的想法要大胆的提出来,两个人能够互补,提出来后才能在思维碰撞下get到最后的答案,但是切忌模糊主题,偏离主要方向
- 开始工作前,先构思好大致的流程和采用的方法,打好稳定的基石,这样可以加快任务的进度,否则真的会做很多无用功!!!